[racket] Why is syntax-e returning a pair and not a list?

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Mon May 27 15:27:53 EDT 2013

A syntax object contains a lot of information in addition to the datum
inside it. Sometimes that datum will be a pair or a list. And
sometimes the extra data needs to be associated with just the pair and
sometimes with all the elements of the list.

If you look at this program:

#lang racket/base
(require (for-syntax racket/base
  (define show-syntax
     [(? syntax? s)
      (printf "syntax from line ~a\n"
              (syntax-line s))
      (show-syntax (syntax-e s))]
     [(? list? l)
      (printf "list\n")
      (for-each show-syntax l)]
     [(? pair? p)
      (printf "pair\n")
      (show-syntax (car p))
      (show-syntax (cdr p))]
     [(? symbol? s)
      (printf "symbol ~a\n" s)])))

(define-syntax (ex stx)
  (show-syntax stx)

(define-syntax (helper1 stx)
  #`(ex #,stx))

(define-syntax (helper2 stx)
  (syntax-case stx ()
    [(_ a ...)
       (ex a ...))]))

(define-syntax (helper3 stx)
  (syntax-case stx ()
    [(_ a ...)
       (ex a ... z))]))

(module+ main
  (ex x)
  (helper1 a b c)
  (helper1 . (a b c))
  (helper2 a b c)
  (helper3 a b c))

You can see how each of the different "helpers" appear to do things
that are very close to one another but turn out to have different
syntax representations.

You normally don't need to worry about this, but sometimes you need to
pay attention to it when you want to get correct source code
origination information. (Basically, if you have a list in the pattern
input and do something like creating a new syntax object like #'(a
...) in a macro and then put that in, then you'll get source code
location information from the macro and not from the source of the
list, which sometimes gets exposed.)


On Mon, May 27, 2013 at 1:06 PM, Tim Nelson <tbnelson at gmail.com> wrote:
> Dear All,
> The documentation for syntax-e says that it may return many different
> types, including a syntax-pair, but it doesn't really describe why. Here's
> a concrete piece of code:
> (define stx
>   (with-syntax ([x #'5]
>                 [(y ...) #'(1 2)])
>     (syntax (x y ...))))
> (syntax->datum stx) returns a list.
> (syntax->list stx) (of course) returns a list, too.
> But (syntax-e stx) returns a pair! If I do this:
> (define stx2
>   (with-syntax ([x #'5]
>                 [y #'(1 2)])
>     (syntax (x y))))
> I get a list from syntax-e, but of course the nesting is wrong/different.
> So my question is: why a pair?
> Best,
> - Tim (Running Racket v. 5.3.3)
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University

"The glory of God is Intelligence" - D&C 93

Posted on the users mailing list.