On 03/06/2014 06:15 PM, Jon Stenerson wrote:
When I run this in DrRacket, the first (m) gives 0 and the second gives
#<procedure:+>.

#lang racket
(m)
(define-syntax m (lambda (stx) #'+))
(m)

Seems a little strange to me. I see why it happens but I guess I had
expected a "use before definition" warning.

This one's fun! I know you know why it happens, but to explain to others:

The first (m) expands to (#%app m). The `m' isn't expanded because it's not defined as a syntax transformer yet. But it isn't transformed into (#%top . m) because `m' is bound in the body of the module.

Then (define-syntax m ...) is expanded. Then (m), which expands to #'+. Now that all the module-level expressions are expanded, the expander starts on their subexpressions, so the first `m' within (m) on line 2 is expanded, and is of course transformed to #'+. The program ends up

  (+)
  (define-syntax m ...)
  +

with each non-definition wrapped in a `print-values', so of course the values 0 and + are printed. Neet.

The way to deal with it is write the syntax transformer so it pattern-matches on how it's called (as the head of a larger expression or not) and expands appropriately:

#lang racket

(m)

(define-syntax (m stx)
  (syntax-case stx ()
    [(_ . es)  (syntax/loc stx (+ . es))]))

(m)

This raises a syntax error on the first (m) because the inner `m' fails to match.

I don't know whether there's any sensible warning Racket can give for the original macro. I'll let the workers of deeper black magic answer that one.

Neil ⊥

____________________
 Racket Users list:
 http://lists.racket-lang.org/users

Reply via email to