@jesse697 has joined the channel
Or even outright prevent you from shadowing variables in many cases
Ive thought of that too… it didnt seem like it would fit well with case->. Oh well maybe I’ll skip if :)
I am having some difficulty with a bit of refactoring. Right now I have this macro:
#lang racket
(define-syntax (statement stx)
#`(let ([op 3]) #,(car (cdr (syntax->datum stx)))))
(statement (+ 1 op))
> 4
And I am trying to change it to something similar to: #lang racket
(define-syntax (statement stx)
(syntax-case stx ()
[(_ operation)
#`(let ([op 3]) #,operation)]))
(statement (+ 1 op))
> operation: pattern variable cannot be used outside of a template in: operation
I can see why I am getting this message, but don’t know of a workaround. Removing the unquote just gives me: > op: unbound identifier
so I am not sure how to unquote at the right time, but still have the expression end up inside of the template.
Hi @michaelrauh Thanks for the great feedback (I’ll send you a mail later).
In this example, I suggest using with-syntax
: (define-syntax (statement stx)
(syntax-case stx ()
[(_ operation)
(with-syntax ([op (datum->syntax stx 'op)])
#'(let ([op 3]) operation))]))
(statement (+ 1 op))
Here with-syntax
binds the pattern variable op
to the result of (datum->syntax stx 'op)
. In the pattern #'(let ([op 3]) operation))
any pattern variables will be replaced with the value to which it is bound.
That makes sense! I will have to see if I can apply this to the more complete example I have been working with. My worry is that it may be tough to apply this pattern when there are many things like op
and I don’t know how many there will be up front. Thank you for the help!
Note that the left-hand side of with-syntax
is a pattern, so something like: (syntax-case stx ()
(with-syntax ([(op ...) (map (lambda (op) (datum->syntax stx op))
(syntax->list #'(op ...)))])
#'(let ([op 3] ...)
operation)))
would handle multiple ops.
Oh, that is very helpful. That would have taken me quite some time to figure out (mostly the map
and syntax->list
parts)
Actually, instead of syntax->list
, you should use '(op op2 op3)
directly
syntax->list
creates a list of identifiers in this case
so datum->syntax
won’t work correctly
IIUC
@soegaard2, I read your Mythical Macros draft 1. Great stuff so far. I loved it. That fits my psychology so well. I believe you caught some typos already. The first (define b x) should’ve been (define b a). I think you meant that. On page 2, the sentence “Given a template syntax will construct a syntax object from the template and replace any identifiers any bound pattern variables.” seems hard to parse and understand. Maybe something like — Given a template[,] syntax will construct a syntax object from the template and replace any identifiers [in] any bound pattern variables. Still not sure what is the real sentence there.
I went very well up until section 3.1. I replaced read with read-syntax, but couldn’t replace expand with expand-syntax. I get ; fact.rkt::2: begin: unbound identifier;
; also, no #%app syntax transformer is bound
; at: begin
; in: (begin (define (fact n) (cond ((= n 0) 1) (else (* n (fact (- n 1)))))) (fact 5))
My code was (I only changed read to read-syntax and expand to expand-syntax): (define ns (make-base-namespace)) ; expand and eval
(parameterize ([current-namespace ns] ; need a namespace
[read-accept-compiled #t])
(define input (open-input-string source))
(define before (read-syntax "fact.rkt" input))
(define after (expand-syntax before))