On this page:
current-syntax-context
wrong-syntax
define/ with-syntax
define-pattern-variable
with-temporaries
generate-temporary
generate-n-temporaries
current-recorded-disappeared-uses
with-disappeared-uses
syntax-local-value/ record
record-disappeared-uses
format-symbol
format-id
format-unique-id
internal-definition-context-apply
syntax-local-eval
with-syntax*
syntax-map
syntax-list
to-syntax
26.1 Syntax Object Source Locations
syntax-source-directory
syntax-source-file-name
26.2 Macro Transformers
redirect-transformer
head-expand
trampoline-transformer
quote-transformer
Version: 5.1

26 Syntax

Ryan Culpepper <ryanc@racket-lang.org>

 (require unstable/syntax)

This library is unstable; compatibility will not be maintained. See Unstable for more information.

The current contextual syntax object, defaulting to #f. It determines the special form name that prefixes syntax errors created by wrong-syntax.

(wrong-syntax stx format-string v ...)  any
  stx : syntax?
  format-string : string?
  v : any/c
Raises a syntax error using the result of (current-syntax-context) as the “major” syntax object and the provided stx as the specific syntax object. (The latter, stx, is usually the one highlighted by DrRacket.) The error message is constructed using the format string and arguments, and it is prefixed with the special form name as described under current-syntax-context.

Examples:

  > (wrong-syntax #'here "expected ~s" 'there)

  ?: expected there

  > (parameterize ((current-syntax-context #'(look over here)))
      (wrong-syntax #'here "expected ~s" 'there))

  eval:4:0: look: expected there at: here in: (look over here)

A macro using wrong-syntax might set the syntax context at the very beginning of its transformation as follows:
  (define-syntax (my-macro stx)
    (parameterize ((current-syntax-context stx))
      (syntax-case stx ()
        __)))
Then any calls to wrong-syntax during the macro’s transformation will refer to my-macro (more precisely, the name that referred to my-macro where the macro was used, which may be different due to renaming, prefixing, etc).

(define/with-syntax pattern expr)
Definition form of with-syntax. That is, it matches the syntax object result of expr against pattern and creates pattern variable definitions for the pattern variables of pattern.

Examples:

  > (define/with-syntax (px ...) #'(a b c))
  > (define/with-syntax (tmp ...) (generate-temporaries #'(px ...)))
  > #'([tmp px] ...)

  #<syntax:7:0 ((a1 a) (b2 b) (c3 c))>

Evaluates expr and binds it to id as a pattern variable, so id can be used in subsequent syntax patterns.

Examples:

  > (define-pattern-variable name #'Alice)
  > #'(hello name)

  #<syntax:9:0 (hello Alice)>

(with-temporaries (temp-id ...) . body)
Evaluates body with each temp-id bound as a pattern variable to a freshly generated identifier.

Example:

  > (with-temporaries (x) #'(lambda (x) x))

  #<syntax:10:0 (lambda (x4) x4)>

(generate-temporary [name-base])  identifier?
  name-base : any/c = 'g
Generates one fresh identifier. Singular form of generate-temporaries. If name-base is supplied, it is used as the basis for the identifier’s name.

Generates a list of n fresh identifiers.

Parameter for tracking disappeared uses. Tracking is “enabled” when the parameter has a non-false value. This is done automatically by forms like with-disappeared-uses.

(with-disappeared-uses stx-expr)
 
  stx-expr : syntax?
Evaluates the stx-expr, catching identifiers looked up using syntax-local-value/catch. Adds the caught identifiers to the 'disappeared-uses syntax property of the resulting syntax object.

(syntax-local-value/record id predicate)  any/c
  id : identifier?
  predicate : (-> any/c boolean?)
Looks up id in the syntactic environment (as syntax-local-value). If the lookup succeeds and returns a value satisfying the predicate, the value is returned and id is recorded as a disappeared use. If the lookup fails or if the value does not satisfy the predicate, #f is returned and the identifier is not recorded as a disappeared use.

(record-disappeared-uses ids)  void?
  ids : (listof identifier?)

If not used within the extent of a with-disappeared-uses form or similar, has no effect.

(format-symbol fmt v ...)  symbol?
  fmt : string?
  v : (or/c string? symbol? identifier? keyword? char? number?)
Like format, but produces a symbol. The format string must use only ~a placeholders. Identifiers in the argument list are automatically converted to symbols.

Example:

  > (format-symbol "make-~a" 'triple)

  'make-triple

(format-id lctx    
  [#:source src    
  #:props props    
  #:cert cert]    
  fmt    
  v ...)  identifier?
  lctx : (or/c syntax? #f)
  src : (or/c syntax? #f) = #f
  props : (or/c syntax? #f) = #f
  cert : (or/c syntax? #f) = #f
  fmt : string?
  v : (or/c string? symbol? identifier? keyword? char? number?)
Like format-symbol, but converts the symbol into an identifier using lctx for the lexical context, src for the source location, props for the properties, and cert for the inactive certificates. (See datum->syntax.)

The format string must use only ~a placeholders. Identifiers in the argument list are automatically converted to symbols.

Examples:

  > (define-syntax (make-pred stx)
      (syntax-case stx ()
        [(make-pred name)
         (format-id #'name "~a?" (syntax-e #'name))]))
  > (make-pred pair)

  #<procedure:pair?>

  > (make-pred none-such)

  reference to undefined identifier: none-such?

  > (define-syntax (better-make-pred stx)
      (syntax-case stx ()
        [(better-make-pred name)
         (format-id #'name #:source #'name
                    "~a?" (syntax-e #'name))]))
  > (better-make-pred none-such)

  reference to undefined identifier: none-such?

(Scribble doesn’t show it, but the DrRacket pinpoints the location of the second error but not of the first.)

This binding was added by Vincent St-Amour.

(format-unique-id lctx    
  [#:source src    
  #:props props    
  #:cert cert]    
  fmt    
  v ...)  identifier?
  lctx : (or/c syntax? #f)
  src : (or/c syntax? #f) = #f
  props : (or/c syntax? #f) = #f
  cert : (or/c syntax? #f) = #f
  fmt : string?
  v : (or/c string? symbol? identifier? keyword? char? number?)
Like format-id, but returned identifiers are guaranteed to be unique.

(internal-definition-context-apply intdef-ctx    
  stx)  syntax?
  intdef-ctx : internal-definition-context?
  stx : syntax?
Applies the renamings of intdef-ctx to stx.

(syntax-local-eval stx [intdef-ctx])  any
  stx : syntax?
  intdef-ctx : (or/c internal-definition-context? #f) = #f
Evaluates stx as an expression in the current transformer environment (that is, at phase level 1), optionally extended with intdef-ctx.

Examples:

  > (define-syntax (show-me stx)
      (syntax-case stx ()
        [(show-me expr)
         (begin
           (printf "at compile time produces ~s\n"
                   (syntax-local-eval #'expr))
           #'(printf "at run time produes ~s\n"
                     expr))]))
  > (show-me (+ 2 5))

  at compile time produces 7

  at run time produes 7

  > (define-for-syntax fruit 'apple)
  > (define fruit 'pear)
  > (show-me fruit)

  at compile time produces apple

  at run time produes pear

The subsequent bindings were added by Sam Tobin-Hochstadt.

(with-syntax* ([pattern stx-expr] ...)
  body ...+)
Similar to with-syntax, but the pattern variables are bound in the remaining stx-exprs as well as the bodys, and the patterns need not bind distinct pattern variables; later bindings shadow earlier bindings.

Example:

  > (with-syntax* ([(x y) (list #'val1 #'val2)]
                   [nest #'((x) (y))])
      #'nest)

  #<syntax:22:0 ((val1) (val2))>

(syntax-map f stxl ...)  (listof A)
  f : (-> syntax? A)
  stxl : syntax?
Performs (map f (syntax->list stxl) ...).

Example:

  > (syntax-map syntax-e #'(a b c))

  '(a b c)

The subsequent bindings were added by Carl Eastlund <cce@racket-lang.org>.

(syntax-list template ...)
This form constructs a list of syntax objects based on the given templates. It is equivalent to (syntax->list #'(template ...)).

Example:

  > (with-syntax ([(x ...) #'(1 2 3)])  (syntax-list x ...))

  '(#<syntax:3:0 1> #<syntax:3:0 2> #<syntax:3:0 3>)

(to-syntax datum    
  [#:stx stx    
  #:src src    
  #:ctxt ctxt    
  #:prop prop    
  #:cert cert])  syntax?
  datum : any/c
  stx : (or/c false/c syntax?) = #f
  src : src/c = stx
  ctxt : (or/c false/c syntax?) = stx
  prop : (or/c false/c syntax?) = stx
  cert : (or/c false/c syntax?) = stx
A wrapper for datum->syntax with keyword arguments.

The "master" keyword #:stx sets all attributes from a single syntax object, defaulting to #f for unadorned syntax objects.

The individual keywords #:src, #:ctxt, #:prop, and #:cert override #:stx for individual syntax object attributes. They control source src information, lexical context information, syntax object properties, and syntax certificates, respectively.

Examples:

  (define blank-stx (to-syntax 'car))
  > blank-stx

  #<syntax car>

  > (syntax-e blank-stx)

  'car

  > (free-identifier=? blank-stx #'car)

  #f

  (define full-stx (to-syntax 'car #:stx #'here))
  > full-stx

  #<syntax:7:0 car>

  > (syntax-e full-stx)

  'car

  > (free-identifier=? full-stx #'car)

  #t

  (define partial-stx (to-syntax 'car #:ctxt #'here))
  > partial-stx

  #<syntax car>

  > (syntax-e partial-stx)

  'car

  > (free-identifier=? partial-stx #'car)

  #t

26.1 Syntax Object Source Locations

(syntax-source-directory stx)  (or/c path? #f)
  stx : syntax?
(syntax-source-file-name stx)  (or/c path? #f)
  stx : syntax?
These produce the directory and file name, respectively, of the path with which stx is associated, or #f if stx is not associated with a path.

Examples:

  (define loc
    (list (build-path "/tmp" "dir" "somewhere.ss")
          #f #f #f #f))
  (define stx1 (datum->syntax #f 'somewhere loc))
  > (syntax-source-directory stx1)

  #<path:/tmp/dir/>

  > (syntax-source-file-name stx1)

  #<path:somewhere.ss>

  (define stx2 (datum->syntax #f 'nowhere #f))
  > (syntax-source-directory stx2)

  #f

  > (syntax-source-directory stx2)

  #f

26.2 Macro Transformers

Constructs a function that behaves like a rename transformer; it does not cooperate with syntax-local-value like a rename transformer does, but unlike a rename transformer it may be used as a function to transform a syntax object referring to one identifier into a syntax object referring to another.

Examples:

  > ((redirect-transformer #'x) #'a)

  #<syntax:3:0 x>

  > ((redirect-transformer #'y) #'(a b c))

  #<syntax:4:0 (y b c)>

(head-expand stx [stop-list] intdef-ctx)  syntax?
  stx : syntax?
  stop-list : (listof identifier?) = null
  intdef-ctx : 
(or/c internal-definitions-context?
      (non-empty-listof internal-definitions-context?)
      #f)
This function performs head expansion on stx. In other words, it uses local-expand to expand stx until its head identifier is a core form (a member of (kernel-form-identifier-list)) or a member of stop-list, or until it can not be expanded further (e.g. due to error).

It is equivalent to (local-expand stx (syntax-local-context) (append stop-ids (kernel-form-identifier-list) intdef-ctx)).

Produces a transformer that can emit multiple results during macro expansion, to be spliced together via begin. This can be useful for compound expansion that relies on transformer definitions, as well as on expansion state that is difficult to marshall.

Specifically, f is invoked with three arguments. The first is the function used to emit intermediate results (other than the last one). The second applies the syntax mark used for the entire expansion; syntax-local-introduce will not be reliable during this process. The third is the syntax object to expand.

Examples:

  > (define-syntax magic-begin
      (trampoline-transformer
       (lambda (emit intro stx)
         (syntax-case stx ()
           [(_ term ...)
            (let loop ([terms (syntax->list #'(term ...))])
              (cond
               [(null? terms) #'(begin)]
               [(null? (cdr terms)) (car terms)]
               [else
                (printf "Presto: ~s!\n"
                        (syntax->datum (car terms)))
                (emit (car terms))
                (loop (cdr terms))]))]))))
  (magic-begin
   (define x 1)
   (define y 2)
   (+ x y))

  Presto: (define x 1)!

  Presto: (define y 2)!

  3

(quote-transformer x)  syntax?
  x : any/c
Produces a syntax object representing an expression that reconstructs x when executed, including faithfully reconstructing any syntax objects contained in x. Note that quote normally converts syntax objects to non-syntax data, and quote-syntax does the opposite.

Examples:

  > (define-for-syntax x (list 1 #'(2 3) 4))
  > (define-syntax (the-many-faces-of-x stx)
      (with-syntax ([x x] [qx (quote-transformer x)])
       #'(list 'x
               (quote-syntax x)
               qx)))
  > (the-many-faces-of-x)

  '((1 (2 3) 4) #<syntax (1 (2 3) 4)> (1 #<syntax:3:0 (2 3)> 4))