Using `~literal` matches by binding, so when `add` is bound by a user's
program (shadowing the binding `provide`d from your `calc` module), it no
longer matches. You can use `~datum` instead to match `add` symbolically —
if you do that in combination with providing an error-raising macro for
`add`, you will get an error if the user uses `add` out of context while
still allowing her to shadow `add` without interfering with its use in
`calc`. (The tradeoff is that the user can no longer use e.g. `rename-in`
to get a symbolically different form of `add` that still works with calc.)
I am not immediately sure why having a `define` around expression 2 makes a
difference, though. I would have expected both expressions to expand to
`'(begin)` when the `(define (add x) (add1 x))` un-commented — which is
what happens if you put that `define` before expression 1.
Here is a version of `calc` that does what I think you want:
#lang racket
(module calc2 racket
(provide calc add)
(require (for-syntax syntax/parse))
(define-syntax (add stx)
(raise-syntax-error #f "used out of context" stx))
(define-syntax calc
(syntax-parser
#:datum-literals (add)
[(_ (~alt (add x y)
ignore:expr)
...)
#''(begin (printf "~a~n" (+ x y)) ...)])))
(require 'calc2)
; (expression 1)
(calc (add 4 5)
(sub 10 7)
(add 9 10))
; (expression 2)
(define A
(calc (add 4 5)
(sub 10 7)
(add 9 10)))
A ; see what A ends up being
(define (add x) (add1 x)) ;the same with or without this
-Philip
On Fri, Oct 20, 2017 at 11:11 PM, Nadeem Abdul Hamid wrote:
> I'm working on a macro that I'd like to work similar to the 'big-bang'
> macro of 2htdp/universe with its various clauses, but something's going on
> that I don't understand. At the bottom of this email is some code for a
> very simple macro, 'calc', that is not what I'm working on, but exhibits
> the puzzling behavior. Here, I'm trying to have an expression like
> (calc (add 5 6) (add 10 9))
> expand to a block of some other expressions. Just like the behavior of
> big-bang, I'd like to raise an error if (add ...) is used in a context
> other than as a clause of 'calc'. But I also don't want it to get confused
> with another definition of 'add' in the user code.
>
> With the code below, when run as is, it does what I want - the (calc ...)
> expressions - one a top-level expression and the one in (define A (calc
> ...)) both expand to a (quoted) s-expression (just for debugging purposes),
> namely:
>
> '(begin
>(printf "~a~n" (+ 4 5))
>(printf "~a~n" (+ 9 10)))
>
> But, if you uncomment the last two lines, which introduces another
> definition of 'add', then the first expression still produces the same as
> above, but the expansion of the 'A' expression is just '(begin). It seems
> like the syntax-parse is no longer matching correctly against the (~literal
> add).
>
> Actually, 'big-bang' also suffers from this same problem -- if you do
> (big-bang 0 (on-tick ...)) as a top-level expression in a file with a
> definition of (define on-tick add1), it works fine. But if you put the
> 'big-bang' inside a define: (define X (big-bang 0 (on-tick ...))) and
> don't change anything else it complains about the on-tick "... keyword
> being used as a variable..."
>
> Why does this happen and is there a way to get around this problem -- i.e.
> have the behavior of the program below be exactly the same whether there is
> a 'define' around the macro use or not?
>
> Thanks very much for any insight!
>
> --- nadeem
>
>
>
> ;;;
> #lang racket
>
> (module calc racket
> (provide calc add)
>
> (require (for-syntax syntax/parse))
>
> (define-for-syntax out-of-context (lambda (stx) (raise-syntax-error #f
> "used out of context" stx)))
> (define-syntax add out-of-context)
>
> (define-for-syntax (process-clauses clauses)
> (syntax-parse clauses
> [(((~literal add) x y) cs ...) #`((printf "~a~n" (+ x y ))
> #,@(process-clauses #'(cs ...)
> ))]
> [(c cs ...) (process-clauses #'(cs ...))] ; skip unexpected
> clauses for now
> [_ #'()]))
>
> (define-syntax (calc stx)
> (syntax-parse stx
> [(calc c ...)
>(let ([adds (process-clauses #'(c ...))])
> #`'(begin #,@adds))])))
>
>
> (require 'calc)
>
> ; (expression 1)
> (calc (add 4 5)
> (sub 10 7)
> (add 9 10))
>
> ; (expression 2)
> (define A
> (calc (add 4 5)
> (sub 10 7)
> (add 9 10)))
> A ; see what A ends up being
>
> ; uncomment these to see different output from the preceding expressions:
> ;(define (add x) (add1 x))
> ;(add 6)
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to