Re: [racket-users] Macro confusion with syntax-parse

2017-10-20 Thread Philip McGrath
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 

[racket-users] Macro confusion with syntax-parse

2017-10-20 Thread Nadeem Abdul Hamid
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.