Your textual manipulation of identifiers is unhygienic. You will need to do the following
(with-syntax ([newX (datum->syntax #'x (translate-symbol (syntax-e #'x)))]) ...use-of-newX...) This means "take the lexical context of x and mark this new symbol as being in the same context." This allows you to capture names in the calling scope without being given them explicitly. As for your concern with syntax-case, that's perfectly fine. Hygiene is assured with both syntax-case and syntax-rules. -Ian ----- Original Message ----- From: "Răzvan Rotaru" <[email protected]> To: "Carl Eastlund" <[email protected]> Cc: [email protected] Sent: Sunday, December 4, 2011 11:42:30 PM GMT -05:00 US/Canada Eastern Subject: Re: [racket] beginner question about macros On 5 December 2011 04:06, Carl Eastlund <[email protected]> wrote: > Răzvan, > > Both of these are in some sense advanced macros. If you're just > learning how to write macros, I'd suggest slightly simpler forms. > > In the first case, write (my-macro (a 1) (b 2) (c 3)) instead. > Grouping the names and numbers with parentheses means there's less > work to do when parsing the macro. Then you can write the whole thing > with one clause. > > (define-syntax my-macro > (syntax-rules () > [(_ (name number) ...) > (let ([x foo]) > (name number x) > ...)])) > Ok, using parens is no problem for me. I tried using syntax rules, inspired by the example from J. Ian Johnson, but ran into the fact that generating the code for each pair (name number), which is recursive requires access to the let-variable. So if I have a my-macro-aux, which deals with (name number) pairs, then it needs to get some info from the calling macro my-macro. Here's the code: (define-syntax gen-pairs (syntax-rules () [(_ k v) (printf "~a ~a ~a~n" <x-from-let-here> k v)] [(_ k v rest ...) (begin (printf "~a ~a ~a~n" <x-from-let-here> k v) (gen-options rest ...))] [(_ rest ...) (raise-syntax-error #f "Expected even number of inputs to gen-pairs")])) (define my-macro (syntax-rules () [(_ rest ...) (let ([x foo]) (gen-pairs rest ...)])) I've also managed to come up with a syntax-case version, though at the moment i'm not 100% sure it's correct. It's basically written by thinking in lisp macro style, and using syntax-quote instead of quote (there's an extra foo as first arg, but otherwise the macro is the same): (define-syntax (my-macro stx) (syntax-case stx () [(_ foo rest ...) #`(let ([x foo]) #,@(let ([args (partition-by (syntax->list #'(rest ...)) 2)]) ;;(partition-by '(1 2 3 4)) => '((1 2)(3 4)) ;;TODO - check that args has at least 2 elements (for/list ([x args]) #`(printf "~a ~a ~a~n" x #,(car args) #,(cadr args)))) )])) Is it safe to approach macros like this? Thinking like lisp, but using #' instead of ' ? > In the second case, it's not clear what you're trying to accomplish. > What are new-a, second-b, and another-c supposed to be? The way you > wrote it, they appear to just be made up, random names that aren't > bound and will immediately lead to syntax errors. I'm sure that's not > what you meant. Can you clarify whether these names are supposed to > be bound inside the macro or somewhere else, and how the macro is > supposed to come up with their names? > > Carl Eastlund new-a, second-b and another-c already exist in the caller environment. I'm trying to generate java calls (in kawa) from macros. Something like: (create-object MyObject X "1" Y "2") => (MyObject) ;instantiation (*:setX "1") ;set value for X (*:setY "2") ;set value for Y And this should work with any X or Y. In other words I need a textual transformation from X to setX to be done in the macro, which will of course fail if setX does not exist (but that's ok). Razvan _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users

