jesse697
2020-12-30 08:22:07

@jesse697 has joined the channel


notjack
2020-12-30 12:03:48

Or even outright prevent you from shadowing variables in many cases


ben.knoble
2020-12-30 15:07:31

Ive thought of that too… it didnt seem like it would fit well with case->. Oh well maybe I’ll skip if :)


michaelrauh
2020-12-30 15:15:06

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.


soegaard2
2020-12-30 15:22:02

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))


soegaard2
2020-12-30 15:23:59

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.


michaelrauh
2020-12-30 15:26:21

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!


soegaard2
2020-12-30 15:31:06

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.


michaelrauh
2020-12-30 15:33:01

Oh, that is very helpful. That would have taken me quite some time to figure out (mostly the map and syntax->list parts)


sorawee
2020-12-30 15:33:34

Actually, instead of syntax->list, you should use '(op op2 op3) directly


sorawee
2020-12-30 15:33:45

syntax->list creates a list of identifiers in this case


sorawee
2020-12-30 15:33:55

so datum->syntax won’t work correctly


sorawee
2020-12-30 15:33:56

IIUC


anything
2020-12-31 03:28:27

@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))