[racket] help: how to make eval see local bindings?

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Mon Jul 11 11:26:49 EDT 2011

This sounds a bit confused. Allow me to tease out a clarification. 

1. If you write a macro like this: 

(define-syntax mym 
  (syntax-rules ()
    [(_ input ...)
     (let* ([x 10])
       (lambda (stuff)
         input ...        ;; line 2 

'hygiene' gives you a couple of different things: 

-- the x and the stuff introduced in the macro doesn't accidentally interfere with free variables in input ... on line 2

-- the let* and the lambda are guaranteed to refer to the meaning in place where you define the macro 

2. So when you run this expression in the context of mym 

(let ([x 42])           ;; line 9
  ((mym (displayln x))  ;; line 7

you see 

-- the output 42 from the displayln on line 7 
-- the result 10 from the line below line 2 

3. It is rare that mym needs to generate code involving the x on line 9 WITHOUT specifying the x in an input position for mym. 

QUESTION: can you explain why you'd want to do so? 
POSSIBLE ANSWER: you may wish to break hygiene then. 

4. It is equally rare that you want let* or lambda to mean what the context of the macro call says they are. 

IF THIS IS WHAT YOU WANT, can you provide more details. 

On Jul 11, 2011, at 11:04 AM, Maurizio Giordano GMAIL wrote:

> On Mon, 2011-07-11 at 13:43 +0100, Noel Welsh wrote:
>> On Mon, Jul 11, 2011 at 1:26 PM, Maurizio Giordano GMAIL
>> <maurizio.giorda at gmail.com> wrote:
>>> PS. my lambda is generated by a macro (define-syntax) ...
>>> this is why I use eval to generate the corresponding procedure.
>> If this is the case I don't think you need to use eval. You either
>> need to write your macro in a hygenic way -- it accepts as parameters
>> all the identifiers in the enclosing environment that is should
>> reference -- or you should explicitly break hygiene. If you're new-ish
>> to Racket the preceeding sentence probably won't make any sense, so
>> feel free to ask for more help!
>> Cheers,
>> N.
> Hi Nole,
> Yes, I am an absolute new-ish to racket... I would like to know more
> about writing a macro by "explicitly break hygiene". 
> I supposed I didn't need to use eval... but for me it is 
> the easiest way to "build" a lambda-code and then evaluate it.
> I want to give you more details about my problem.
> I have a macro like this:
> (define-syntax mymacro
>  (syntax-rules (mymacro)
>    [(mymacro input ...)
>     (let* (...)
>       (eval `(lambda (cntx) 
>                 ...      ; a code generated according to macro
> "input ..."
>                 (+ x 2)  ; that contains references to an outside "x"
> symbol
>                 ...
>              ))]))
> Note that I cannot foresee which extern symbols are referenced by the 
> generated lambda.
> This macro returns a procedure.
> if I use my macro in a "let" construct, of course I have a "reference to
> an undefined identifier":  
> (let* ((x 1) 
>       (f (mymacro ...)))
>     (f 2))
> reference to undefined identifier: x
> So, coming back to my question: since the eval is called within the
> "let"
> scope, is it possible to make it aware of the bindings of the "let"? 
> Do you know alternative mechanism to do that?
> TIA,
> Cheers,
> Maurizio.
> _________________________________________________
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/users

Posted on the users mailing list.