:wave: it’s me again! As part of a macro, I’m trying to change the name of an identifier but I’m running into issues.
(define-for-syntax (identifier-append id string)
(datum->syntax #f (string->symbol (string-append (symbol->string (syntax->datum id)) string))))
(define-syntax (define-new stx)
(syntax-case stx ()
[(define-purpose name)
(let ([new-name (identifier-append #'name "-new")])
#'(define new-name "bob"))]))
What I want is that a call to (define-new hello)
would be equivalent to (define hello-new "bob")
the above code is what I have so far, but with that, the result I get is (define new-name "bob")
instead of (define hello-new "bob")
@khepin I think you want with-syntax
instead of let
- using let
creates a variable at phase 1 (compile time), but the use of new-name
inside your template (the #'
part) is at phase 0 so it doesn’t see your let
binding
but with-syntax
binds pattern variables to syntax objects, not regular variables to arbitrary values, and those pattern variables can be used in syntax
templates - note that #'(foo bar baz)
is equivalent to (syntax (foo bar baz))
thanks! I’m reading through the docs on with-syntax
now, this looks like what I need indeed!
@khepin have you read greg’s Fear of Macros tutorial? I would have been lost without it when I was learning this stuff
I have not yet!
A more subtle point with ‘hygienic macros’ is you have to syntax-local-introduce
on the new identifier, otherwise the new identifier will only be available inside the macro (with-syntax ([new-name
(syntax-local-introduce
(identifier-append #'name "-new"))])
...
YASS!!! that was the missing part!
thanks to both of you!
or you may use the original context: (datum->syntax
id
(string->symbol (string-append (symbol->string (syntax->datum id)) string)))
you may also be interested in the format-id
function
oh, while on that, I did pass #f
as the context for (datum->syntax) . But I was wondering how I would pass “whatever the context of the original id was”
@khepin you could pass the id to the context argument directly
it accepts syntax objects
ooohhh
format-id
will do that too, so your macro would be:
(define-syntax (define-new stx)
(syntax-case stx ()
[(define-purpose name)
(with-syntax ([new-name (format-id #'name "~a-new" #'name)])
#'(define new-name "bob"))]))
(disclaimer: I have only written the above code, not run it…)
p.s. as a bonus: if datum->syntax gets the original source location and properties (the third and fourth argument) (datum->syntax
id
(string->symbol (string-append (symbol->string (syntax->datum id)) string))
id
id)
then hovering your mouse over “hello” and “hello-new” in DrRacket will give you a surprise :wink: