Well, perhaps eval is the only way to go. There are situations where you need it; otherwise it wouldn't be there - Matthias
On Jul 13, 2011, at 5:30 PM, Maurizio Giordano wrote: > Hi Matthias, hi all > > 2011/7/13 Matthias Felleisen <matth...@ccs.neu.edu> > > > [I hadn't forgotten your messages, it's just that deadlines got in the way.] > > I still don't understand your desire to access the environmental variables > specially: > > 1. if you generate a closure or a struct full of closures in your macro, the > expression that you pass in captures the variables in its context: > > > (define-syntax-rule (mystuff y expr) (lambda (x) (displayln `(expr ,y)) (if > > expr x 0))) > > [ (let ((t 333)) (mystuff t (> t 444))) 22] > ((> t 444) 333) > 0 > > See it really does get t's value from the context. > > Yes it does ... I know that if the macro returns the lambda ... > no problem, unfortunately my macro returns something like: > (eval `(lambda ...)) > Now the question is: Can I rewrite my macro to generate the same code > without using the "(eval `(lambda ...))"? > I don't know, I feel yes ... but at the moment I don't know how to > redesign it. > My lambda code is not a predefined template > (the quasiquote) with some small parts to be instantiated (with unquoting). > First, the lambda code is very large, > Second, it is recursively produced by an expander function (used in the > macro). > When you call the macro, you don't know in advance how many times > the expander will call itself. It is something like: > > (define-syntax-rule replace > ... > (eval `(lambda (x) > ... static part ... > ,(expander ...) ; this inject a part of the lambda code > ...))) > > (define (expander ...) > `(let ((...)) > ... static part ... > ,(expander ...) ; injection once again > ...)) > > 2a. do you have reason to access variables other than throwing them into the > environment for eval? In that case your problem is solved. > > 2b. if not, what are the reasons to guess at variable names in the context of > the macro USE (not definition)? > > I try to answer to both questions: > > My macro is the primitive of a new language: > > < elem1, elem2, ... , (replace x y by (+ x y) if (> x othervar)) > > > the replace macro has the following inputs: > x, y = free variables to be matched on a set of elements (<...>) > (+ x y) = a form to be inserted in the set inspite of x and y > (> x othervar) = a conditional form: here x is matched (bound) locally, > othervar is a symbol "outside" the set (that is the scheme top env or > any other inner env like a let) > This is why I need that the produced lambda USE outside symbols. > At the moment, in my implementation, the lambda can use outside > symbols if they are defined in the top env ... I would like to have it also in > inner environments. > > > ;; ---------------- > > > SEPARATE QUESTION: Now you also write that you process the code before you > throw it to eval. Is it possible to write functions on syntax that process > the code and perform the optimizations that Racket doesn't perform for you? > > That's an interesting question: yes ... I process A LOT the code before > I throw it to the eval ... as I said you it is like a compiler (... my first > research area... many years ago!) > First: I generate recursively the code with a my expander function (not the > one of racket) > Second: I (try) to generate an efficient code to simulate the runtime of the > language (the chemical language) I have implemented on top of racket. > If you look at the generated code, you can figure out several optimizations. > One is "inlining": if I have a lambda (in my case a chemical rule) that will > be executed many times (on all possible combinations of elements in a set), > and each time the lambda may use recursion, than, from my experience it is > better to explode recursive calls in recursive inlining of code. > From your question I understand that you mean "optimizations of racket > code" that racket does not do. > > Absolutely an interesting discussion... thanks. > > Cheers, > Maurizio. > > -- Matthias > > > > > > > On Jul 13, 2011, at 3:54 PM, Maurizio Giordano wrote: > > > Hi all, hi Matthias, > > > > I would like to come back to my (still unsolved) problem I > > proposed some days ago: > > > > when using define-syntax in a inner scope of bindings (like let), > > in this example: > > > > (define-syntax mymacro > > (syntax-rules () > > [(_ x) > > (eval `(lambda (w) (print (quote x)) (if x w #f)))])) > > > > (let* ((s 3) (f (mymacro (> s 0)))) (f 5)) > > reference to undefined identifier: s > > > > of course if you: > > > > (define s 3) > > > > in the top environment, the error will not appear. > > This is even more clear if you expand the macro: > > > > (syntax->datum (expand '(mymacro (> s 0)))) > > ... you see that "s" is a %top binding. > > > > I know that if I make the macro to return directly the lambda, > > it works. Nevertheless, in my implementation, I still need to use > > the "(eval (quasiquote (lambda ...)))". > > Why? my macro is like a compiler > > that generates a lambda code very huge: the code is recursive in some of > > its part, > > but, for efficiency reasons, i preferred to inline all recursive calls. So > > I use a > > function "expander" that makes recursive inlining (or injecting) of code). > > It is more or less something like: > > > > `(lambda (...) ... static-code... ,(expander ...) ...) > > > > where "expander call itself with different parameters. > > > > This is just to know your opinion... if the "(eval (quasiquote (lambda > > ...)))" > > cannot see local bindings like in let*, than I have to choice: > > 1) renounce to the feature. > > 2) looking for alternative methods to generate my code with recursive > > inlining > > > > Than you, > > Cheers, > > Maurizio. > > _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users