A new syntax object can be constructed by both syntax/loc
and syntax
(also written #'
).
When should I use syntax/loc
?
Use #'
(i.e. syntax
) when you are not constructing a new syntax object, as when you're just referencing a pattern variable bound with syntax-case
or with-syntax
.
Use #'
for temporary syntax objects as in (syntax->list #'(id ...))
.
Use #'
for syntax objects representing forms that you know won't have syntax errors in them, or where syntax errors in them are the fault of your macro implementation, not the use of your macro.
Use syntax/loc
when you construct expressions that potentially can contain syntax-errors due to an incorrect usage of your macro.
Let's consider a concrete example:
The form display-let
should work exactly like normal let
, except that it displays the values of the bindings before it evaluates the body.
Here is a first implementation:
(define-syntax (display-let-1 stx)
(syntax-case stx ()
[(_ ([id expr] ...) body ...)
#'((lambda (id ...)
(displayln (format "~a is bound to ~a" 'id id)) ...
body ...)
expr ...)]))
Here is an example of a correct use of the macro:
> (display-let-1 ([x 1] [y 2]) (+ x y))
x is bound to 1
y is bound to 2
3
Now let us see what happens when the macro is used incorrectly:
> (display-let-1 ())
lambda: bad syntax in: (lambda ())
This usage is incorrect, since a use of let
must always have a non-empty body. Besides printing the error message, DrRacket colors this code red:
(lambda (id ...)
(displayln (format "~a is bound to ~a" 'id id)) ...
body ...)
Although it is correct that the lambda
expression constructed by the macro is incorrect, (lambda ())
is not legal, it is not due to an error in the macro, but due to an incorrect use of the macro.
To redirect the blame surround the constructed lambda
expression with syntax/loc
and use the first argument of syntax/loc
as place to color red.
(define-syntax (display-let-2 stx)
(syntax-case stx ()
[(display-let ([id expr] ...) body ...)
#`(#,(syntax/loc stx (lambda (id ...) body ...)) expr ...)]))
> (display-let-2 ())
display-let-2: bad syntax in: (display-let-2 ())
This time around the (display-let-2 ())
entered in the repl is colored red, and the error message mentioned display-let-2
instead of lambda
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With