On this page:
2.1 Deconstructing Syntax Objects
stx-null?
stx-pair?
stx-list?
stx->list
stx-car
stx-cdr
stx-map
module-or-top-identifier=?
2.2 Matching Fully-Expanded Expressions
kernel-syntax-case
kernel-syntax-case*
kernel-syntax-case/  phase
kernel-syntax-case*/  phase
kernel-form-identifier-list
2.3 Dictionaries with Identifier Keys
2.3.1 Dictionaries for free-identifier=?
make-free-id-table
make-immutable-free-id-table
free-id-table?
mutable-free-id-table?
immutable-free-id-table?
free-id-table-ref
free-id-table-ref!
free-id-table-set!
free-id-table-set
free-id-table-set*!
free-id-table-set*
free-id-table-remove!
free-id-table-remove
free-id-table-update!
free-id-table-update
free-id-table-map
free-id-table-keys
free-id-table-values
in-free-id-table
free-id-table-for-each
free-id-table-count
free-id-table-iterate-first
free-id-table-iterate-next
free-id-table-iterate-key
free-id-table-iterate-value
id-table-iter?
free-id-table/  c
2.3.2 Dictionaries for bound-identifier=?
make-bound-id-table
make-immutable-bound-id-table
bound-id-table?
mutable-bound-id-table?
immutable-bound-id-table?
bound-id-table-ref
bound-id-table-ref!
bound-id-table-set!
bound-id-table-set
bound-id-table-set*!
bound-id-table-set*
bound-id-table-remove!
bound-id-table-remove
bound-id-table-update!
bound-id-table-update
bound-id-table-map
bound-id-table-keys
bound-id-table-values
in-bound-id-table
bound-id-table-for-each
bound-id-table-count
bound-id-table-iterate-first
bound-id-table-iterate-next
bound-id-table-iterate-key
bound-id-table-iterate-value
bound-id-table/  c
2.4 Sets with Identifier Keys
2.4.1 Sets for free-identifier=?
mutable-free-id-set
immutable-free-id-set
free-id-set?
mutable-free-id-set?
immutable-free-id-set?
free-id-set-empty?
free-id-set-count
free-id-set-member?
free-id-set=?
free-id-set-add
free-id-set-add!
free-id-set-remove
free-id-set-remove!
free-id-set-first
free-id-set-rest
in-free-id-set
free-id-set->stream
free-id-set->list
free-id-set-copy
free-id-set-copy-clear
free-id-set-clear
free-id-set-clear!
free-id-set-union
free-id-set-union!
free-id-set-intersect
free-id-set-intersect!
free-id-set-subtract
free-id-set-subtract!
free-id-set-symmetric-difference
free-id-set-symmetric-difference!
free-id-subset?
free-id-proper-subset?
free-id-set-map
free-id-set-for-each
id-set/  c
free-id-set/  c
2.4.2 Sets for bound-identifier=?
mutable-bound-id-set
immutable-bound-id-set
bound-id-set?
mutable-bound-id-set?
immutable-bound-id-set?
bound-id-set-empty?
bound-id-set-count
bound-id-set-member?
bound-id-set=?
bound-id-set-add
bound-id-set-add!
bound-id-set-remove
bound-id-set-remove!
bound-id-set-first
bound-id-set-rest
in-bound-id-set
bound-id-set->stream
bound-id-set->list
bound-id-set-copy
bound-id-set-copy-clear
bound-id-set-clear
bound-id-set-clear!
bound-id-set-union
bound-id-set-union!
bound-id-set-intersect
bound-id-set-intersect!
bound-id-set-subtract
bound-id-set-subtract!
bound-id-set-symmetric-difference
bound-id-set-symmetric-difference!
bound-id-subset?
bound-id-proper-subset?
bound-id-set-map
bound-id-set-for-each
bound-id-set/  c
2.5 Hashing on bound-identifier=? and free-identifier=?
make-bound-identifier-mapping
bound-identifier-mapping?
bound-identifier-mapping-get
bound-identifier-mapping-put!
bound-identifier-mapping-for-each
bound-identifier-mapping-map
make-free-identifier-mapping
free-identifier-mapping?
free-identifier-mapping-get
free-identifier-mapping-put!
free-identifier-mapping-for-each
free-identifier-mapping-map
make-module-identifier-mapping
module-identifier-mapping?
module-identifier-mapping-get
module-identifier-mapping-put!
module-identifier-mapping-for-each
module-identifier-mapping-map
2.6 Rendering Syntax Objects with Formatting
syntax->string
2.7 Computing the Free Variables of an Expression
free-vars
2.8 Replacing Lexical Context
strip-context
replace-context
2.9 Helpers for Processing Keyword Syntax
parse-keyword-options
parse-keyword-options/  eol
options-select
options-select-row
options-select-value
check-identifier
check-expression
check-stx-listof
check-stx-string
check-stx-boolean

2 Syntax Object Helpers🔗

2.1 Deconstructing Syntax Objects🔗

 (require syntax/stx) package: base

procedure

(stx-null? v)  boolean?

  v : any/c
Returns #t if v is either the empty list or a syntax object representing the empty list (i.e., syntax-e on the syntax object returns the empty list).

Examples:
> (stx-null? null)

#t

> (stx-null? #'())

#t

> (stx-null? #'(a))

#f

procedure

(stx-pair? v)  boolean?

  v : any/c
Returns #t if v is either a pair or a syntax object representing a pair (see syntax pair).

Examples:
> (stx-pair? (cons #'a #'b))

#t

> (stx-pair? #'(a . b))

#t

> (stx-pair? #'())

#f

> (stx-pair? #'a)

#f

procedure

(stx-list? v)  boolean?

  v : any/c
Returns #t if v is a list, or if it is a sequence of pairs leading to a syntax object such that syntax->list would produce a list.

Examples:
> (stx-list? #'(a b c d))

#t

> (stx-list? #'((a b) (c d)))

#t

> (stx-list? #'(a b (c d)))

#t

> (stx-list? (list #'a #'b))

#t

> (stx-list? #'a)

#f

procedure

(stx->list stx-list)  (or/c list? #f)

  stx-list : stx-list?
Produces a list by flatting out a trailing syntax object using syntax->list.

Examples:
> (stx->list #'(a b c d))

'(#<syntax:eval:14:0 a>

  #<syntax:eval:14:0 b>

  #<syntax:eval:14:0 c>

  #<syntax:eval:14:0 d>)

> (stx->list #'((a b) (c d)))

'(#<syntax:eval:15:0 (a b)> #<syntax:eval:15:0 (c d)>)

> (stx->list #'(a b (c d)))

'(#<syntax:eval:16:0 a> #<syntax:eval:16:0 b> #<syntax:eval:16:0 (c d)>)

> (stx->list (list #'a #'b))

'(#<syntax:eval:17:0 a> #<syntax:eval:17:0 b>)

> (stx->list #'a)

#f

procedure

(stx-car v)  any

  v : stx-pair?
Takes the car of a syntax pair.

Examples:
> (stx-car #'(a b))

#<syntax:eval:19:0 a>

> (stx-car (list #'a #'b))

#<syntax:eval:20:0 a>

procedure

(stx-cdr v)  any

  v : stx-pair?
Takes the cdr of a syntax pair.

Examples:
> (stx-cdr #'(a b))

'(#<syntax:eval:21:0 b>)

> (stx-cdr (list #'a #'b))

'(#<syntax:eval:22:0 b>)

procedure

(stx-map proc stxl ...)  list?

  proc : procedure?
  stxl : stx-list?
Equivalent to (map proc (stx->list stxl) ...).

Example:
> (stx-map (λ (id) (free-identifier=? id #'a)) #'(a b c d))

'(#t #f #f #f)

procedure

(module-or-top-identifier=? a-id b-id)  boolean?

  a-id : identifier?
  b-id : identifier?
Returns #t if a-id and b-id are free-identifier=?, or if a-id and b-id have the same name (as extracted by syntax-e) and a-id has no binding other than at the top level.

This procedure is useful in conjunction with syntax-case* to match procedure names that are normally bound by Racket. For example, the include macro uses this procedure to recognize build-path; using free-identifier=? would not work well outside of module, since the top-level build-path is a distinct variable from the racket/base export (though it’s bound to the same procedure, initially).

2.2 Matching Fully-Expanded Expressions🔗

 (require syntax/kerncase) package: base

syntax

(kernel-syntax-case stx-expr trans?-expr clause ...)

A syntactic form like syntax-case*, except that the literals are built-in as the names of the primitive Racket forms as exported by racket/base, including letrec-syntaxes+values; see Fully Expanded Programs.

The trans?-expr boolean expression replaces the comparison procedure, and instead selects simply between normal-phase comparisons or transformer-phase comparisons. The clauses are the same as in syntax-case*.

The primitive syntactic forms must have their normal bindings in the context of the kernel-syntax-case expression. Beware that kernel-syntax-case does not work in a module whose language provides different bindings for these primitive syntactic forms, such as mzscheme which does not provide the primitive if and typed/racket which does not provide the primitive let-values among others.

syntax

(kernel-syntax-case* stx-expr trans?-expr (extra-id ...) clause ...)

A syntactic form like kernel-syntax-case, except that it takes an additional list of extra literals that are in addition to the primitive Racket forms.

syntax

(kernel-syntax-case/phase stx-expr phase-expr clause ...)

Generalizes kernel-syntax-case to work at an arbitrary phase level, as indicated by phase-expr.

syntax

(kernel-syntax-case*/phase stx-expr phase-expr (extra-id ..)
  clause ...)
Generalizes kernel-syntax-case* to work at an arbitrary phase level, as indicated by phase-expr.

Returns a list of identifiers that are bound normally, for-syntax, and for-template to the primitive Racket forms for expressions, internal-definition positions, and module-level and top-level positions. This function is useful for generating a list of stopping points to provide to local-expand.

In addition to the identifiers listed in Fully Expanded Programs, the list includes letrec-syntaxes+values, which is the core form for local expand-time binding and can appear in the result of local-expand.

Changed in version 6.90.0.27 of package base: Added quote-syntax and #%plain-module-begin to the list, which had previously been unintentionally missing.

2.3 Dictionaries with Identifier Keys🔗

 (require syntax/id-table) package: base

This module provides two implementations of identifier tables: dictionaries with identifier keys that use identifier-specific comparisons instead of eq? or equal?. Identifier tables implement the racket/dict interface, and they are available in both mutable and immutable variants.

2.3.1 Dictionaries for free-identifier=?🔗

A free-identifier table is a dictionary whose keys are compared using free-identifier=?. Free-identifier tables implement the dictionary interface of racket/dict, so all of the appropriate generic functions (dict-ref, dict-map, etc) can be used on free-identifier tables.

A caveat for using these tables is that a lookup can fail with unexpected results if the binding of an identifier changes between key-value insertion and the lookup.

For example, consider the following use:

> (define-syntax-rule (m)
    (begin
      (begin-for-syntax
        (define table (make-free-id-table))
        ; set table entry to #t
        (free-id-table-set! table #'x #t)
        ; sanity check, it's set to #t
        (displayln (free-id-table-ref table #'x #f)))
  
      (define x 'defined-now)
  
      (begin-for-syntax
        ; might expect to get #t, but prints #f
        (displayln (free-id-table-ref table #'x #f)))))
> (m)

#t

#f

The macro m expands to code that initializes an identifier table at compile-time and inserts a key-value pair for #'x and #t. The #'x identifier has no binding, however, until the definition (define x 'defined-now) is evaluated.

As a result, the lookup at the end of m will return #f instead of #t because the binding symbol for #'x changes after the initial key-value pair is put into the table. If the definition is evaluated before the initial insertion, both expressions will print #t.

procedure

(make-free-id-table [init-dict    
  #:phase phase])  mutable-free-id-table?
  init-dict : dict? = null
  phase : (or/c exact-integer? #f) = (syntax-local-phase-level)

procedure

(make-immutable-free-id-table [init-dict 
  #:phase phase]) 
  immutable-free-id-table?
  init-dict : dict? = null
  phase : (or/c exact-integer? #f) = (syntax-local-phase-level)
Produces a mutable free-identifier table or immutable free-identifier table, respectively. The dictionary uses free-identifier=? to compare keys, but also uses a hash table based on symbol equality to make the dictionary efficient in the common case.

The identifiers are compared at phase level phase. The default phase, (syntax-local-phase-level), is generally appropriate for identifier tables used by macros, but code that analyzes fully-expanded programs may need to create separate identifier tables for each phase of the module.

The optional init-dict argument provides the initial mappings. It must be a dictionary, and its keys must all be identifiers. If the init-dict dictionary has multiple distinct entries whose keys are free-identifier=?, only one of the entries appears in the new id-table, and it is not specified which entry is picked.

procedure

(free-id-table? v)  boolean?

  v : any/c
Returns #t if v was produced by make-free-id-table or make-immutable-free-id-table, #f otherwise.

procedure

(mutable-free-id-table? v)  boolean?

  v : any/c
Returns #t if v was produced by make-free-id-table, #f otherwise.

procedure

(immutable-free-id-table? v)  boolean?

  v : any/c
Returns #t if v was produced by make-immutable-free-id-table, #f otherwise.

procedure

(free-id-table-ref table id [failure])  any

  table : free-id-table?
  id : identifier?
  failure : any/c = (lambda () (raise (make-exn:fail .....)))
Like hash-ref. In particular, if id is not found, the failure argument is applied if it is a procedure, or simply returned otherwise.

procedure

(free-id-table-ref! table id failure)  any

  table : mutable-free-id-table?
  id : identifier?
  failure : any/c
Like hash-ref!.

Added in version 6.3.0.6 of package base.

procedure

(free-id-table-set! table id v)  void?

  table : mutable-free-id-table?
  id : identifier?
  v : any/c
Like hash-set!.

procedure

(free-id-table-set table id v)  immutable-free-id-table?

  table : immutable-free-id-table?
  id : identifier?
  v : any/c
Like hash-set.

procedure

(free-id-table-set*! table id v ... ...)  void?

  table : mutable-free-id-table?
  id : identifier?
  v : any/c

Added in version 6.3.0.6 of package base.

procedure

(free-id-table-set* table id v ... ...)  immutable-free-id-table?

  table : immutable-free-id-table?
  id : identifier?
  v : any/c
Like hash-set*.

Added in version 6.3.0.6 of package base.

procedure

(free-id-table-remove! table id)  void?

  table : mutable-free-id-table?
  id : identifier?

procedure

(free-id-table-remove table id)  immutable-free-id-table?

  table : immutable-free-id-table?
  id : identifier?

procedure

(free-id-table-update! table    
  id    
  updater    
  [failure])  void?
  table : mutable-free-id-table?
  id : identifier?
  updater : (any/c . -> . any/c)
  failure : any/c = (lambda () (raise (make-exn:fail .....)))

Added in version 6.3.0.6 of package base.

procedure

(free-id-table-update table    
  id    
  updater    
  [failure])  immutable-free-id-table?
  table : immutable-free-id-table?
  id : identifier?
  updater : (any/c . -> . any/c)
  failure : any/c = (lambda () (raise (make-exn:fail .....)))

Added in version 6.3.0.6 of package base.

procedure

(free-id-table-map table proc)  list?

  table : free-id-table?
  proc : (-> identifier? any/c any)
Like hash-map.

procedure

(free-id-table-keys table)  (listof identifier?)

  table : free-id-table?
Like hash-keys.

Added in version 6.3.0.3 of package base.

procedure

(free-id-table-values table)  (listof any/c)

  table : free-id-table?

Added in version 6.3.0.3 of package base.

procedure

(in-free-id-table table)  sequence?

  table : free-id-table?
Like in-hash.

Added in version 6.3.0.3 of package base.

procedure

(free-id-table-for-each table proc)  void?

  table : free-id-table?
  proc : (-> identifier? any/c any)

procedure

(free-id-table-iterate-first table)  id-table-iter?

  table : free-id-table?

procedure

(free-id-table-iterate-next table position)  id-table-iter?

  table : free-id-table?
  position : id-table-iter?

procedure

(free-id-table-iterate-key table position)  identifier?

  table : free-id-table?
  position : id-table-iter?

procedure

(free-id-table-iterate-value table    
  position)  identifier?
  table : bound-it-table?
  position : id-table-iter?

procedure

(id-table-iter? v)  boolean?

  v : any/c
Returns #t if v represents a position in an identifier table (free or bound, mutable or immutable), #f otherwise.

procedure

(free-id-table/c key-ctc    
  val-ctc    
  [#:immutable immutable?])  contract?
  key-ctc : flat-contract?
  val-ctc : chaperone-contract?
  immutable? : (or/c #t #f 'dont-care) = 'dont-care
Like hash/c, but for free-identifier tables. If immutable? is #t, the contract accepts only immutable identifier tables; if immutable? is #f, the contract accepts only mutable identifier tables.

2.3.2 Dictionaries for bound-identifier=?🔗

A bound-identifier table is a dictionary whose keys are compared using bound-identifier=?. Bound-identifier tables implement the dictionary interface of racket/dict, so all of the appropriate generic functions (dict-ref, dict-map, etc) can be used on bound-identifier tables.

procedure

(make-bound-id-table [init-dict    
  #:phase phase])  mutable-bound-id-table?
  init-dict : dict? = null
  phase : (or/c exact-integer? #f) = (syntax-local-phase-level)

procedure

(make-immutable-bound-id-table [init-dict 
  #:phase phase]) 
  immutable-bound-id-table?
  init-dict : dict? = null
  phase : (or/c exact-integer? #f) = (syntax-local-phase-level)

procedure

(bound-id-table? v)  boolean?

  v : any/c

procedure

(mutable-bound-id-table? v)  boolean?

  v : any/c

procedure

(immutable-bound-id-table? v)  boolean?

  v : any/c

procedure

(bound-id-table-ref table id [failure])  any

  table : bound-id-table?
  id : identifier?
  failure : any/c = (lambda () (raise (make-exn:fail .....)))

procedure

(bound-id-table-ref! table id failure)  any

  table : mutable-bound-id-table?
  id : identifier?
  failure : any/c

procedure

(bound-id-table-set! table id v)  void?

  table : mutable-bound-id-table?
  id : identifier?
  v : any/c

procedure

(bound-id-table-set table id v)  immutable-bound-id-table?

  table : immutable-bound-id-table?
  id : identifier?
  v : any/c

procedure

(bound-id-table-set*! table id v ... ...)  void?

  table : mutable-bound-id-table?
  id : identifier?
  v : any/c

procedure

(bound-id-table-set* table id v ... ...)

  immutable-bound-id-table?
  table : immutable-bound-id-table?
  id : identifier?
  v : any/c

procedure

(bound-id-table-remove! table id)  void?

  table : mutable-bound-id-table?
  id : identifier?

procedure

(bound-id-table-remove table id)  immutable-bound-id-table?

  table : immutable-bound-id-table?
  id : identifier?

procedure

(bound-id-table-update! table    
  id    
  updater    
  [failure])  void?
  table : mutable-bound-id-table?
  id : identifier?
  updater : (any/c . -> . any/c)
  failure : any/c = (lambda () (raise (make-exn:fail .....)))

procedure

(bound-id-table-update table    
  id    
  updater    
  [failure])  immutable-bound-id-table?
  table : immutable-bound-id-table?
  id : identifier?
  updater : (any/c . -> . any/c)
  failure : any/c = (lambda () (raise (make-exn:fail .....)))

procedure

(bound-id-table-map table proc)  list?

  table : bound-id-table?
  proc : (-> identifier? any/c any)

procedure

(bound-id-table-keys table)  (listof identifier?)

  table : bound-id-table?

procedure

(bound-id-table-values table)  (listof any/c)

  table : bound-id-table?

procedure

(in-bound-id-table table)  sequence?

  table : bound-id-table?

procedure

(bound-id-table-for-each table proc)  void?

  table : bound-id-table?
  proc : (-> identifier? any/c any)

procedure

(bound-id-table-count table)  exact-nonnegative-integer?

  table : bound-id-table?

procedure

(bound-id-table-iterate-first table)  id-table-position?

  table : bound-id-table?

procedure

(bound-id-table-iterate-next table    
  position)  id-table-position?
  table : bound-id-table?
  position : id-table-position?

procedure

(bound-id-table-iterate-key table position)  identifier?

  table : bound-id-table?
  position : id-table-position?

procedure

(bound-id-table-iterate-value table    
  position)  identifier?
  table : bound-id-table?
  position : id-table-position?

procedure

(bound-id-table/c key-ctc    
  val-ctc    
  [#:immutable immutable])  contract?
  key-ctc : flat-contract?
  val-ctc : chaperone-contract?
  immutable : (or/c #t #f 'dont-care) = 'dont-care
Like the procedures for free-identifier tables (make-free-id-table, free-id-table-ref, etc), but for bound-identifier tables, which use bound-identifier=? to compare keys.

Changed in version 6.3.0.3 of package base: Added bound-id-table-keys, bound-id-table-values, in-bound-id-table.
Changed in version 6.3.0.6: Added bound-id-table-ref!, bound-id-table-set*, bound-id-table-set*!, bound-id-table-update!, and bound-id-table-update

2.4 Sets with Identifier Keys🔗

 (require syntax/id-set) package: base

This module provides identifier sets: sets with identifier keys that use identifier-specific comparisons instead of the usual equality operators such as eq? or equal?.

This module implements two kinds of identifier sets: one via free-identifier=? and one via bound-identifier=?. Each are available in both mutable and immutable variants and implement the gen:set, gen:stream, prop:sequence, and gen:equal+hash generic interfaces.

Identifier sets are implemented using identifier tables, in the same way that hash sets are implemented with hash tables.

2.4.1 Sets for free-identifier=?🔗

A free-identifier set is a set whose keys are compared using free-identifier=?. Free-identifier sets implement the gen:set interface, so all of the appropriate generic functions (e.g., set-add, set-map, etc) can be used on free-identifier sets.

procedure

(mutable-free-id-set [init-set    
  #:phase phase])  mutable-free-id-set?
  init-set : generic-set? = null
  phase : (or/c exact-integer? #f) = (syntax-local-phase-level)

procedure

(immutable-free-id-set [init-set    
  #:phase phase])  immutable-free-id-set?
  init-set : generic-set? = null
  phase : (or/c exact-integer? #f) = (syntax-local-phase-level)
Produces a mutable free-identifier set or immutable free-identifier set, respectively. The set uses free-identifier=? to compare keys.

The identifiers are compared at phase level phase. The default phase, (syntax-local-phase-level), is generally appropriate for identifier sets used by macros, but code that analyzes fully-expanded programs may need to create separate identifier sets for each phase of the module.

The optional init-set argument provides the initial set elements. It must be a set of identifiers. If the init-set set has multiple distinct entries whose keys are free-identifier=?, only one of the entries appears in the new id-set, and it is not specified which entry is picked.

procedure

(free-id-set? v)  boolean?

  v : any/c
Returns #t if v was produced by mutable-free-id-set or immutable-free-id-set, #f otherwise.

procedure

(mutable-free-id-set? v)  boolean?

  v : any/c
Returns #t if v was produced by mutable-free-id-set, #f otherwise.

procedure

(immutable-free-id-set? v)  boolean?

  v : any/c
Returns #t if v was produced by immutable-free-id-set, #f otherwise.

procedure

(free-id-set-empty? s)  boolean?

  s : free-id-set?

Like set-count.

procedure

(free-id-set-member? s v)  boolean?

  s : free-id-set?
  v : identifier?

procedure

(free-id-set=? s1 s2)  boolean?

  s1 : free-id-set?
  s2 : free-id-set?
Like set=?.

Like set-add.

procedure

(free-id-set-add! s v)  void?

  s : mutable-free-id-set?
  v : identifier?
Like set-add!.

procedure

(free-id-set-remove! s v)  void?

  s : mutable-free-id-set?
  v : identifier?

procedure

(free-id-set-first s)  identifier?

  s : free-id-set?
Like set-first.

Like set-rest.

procedure

(in-free-id-set s)  sequence?

  s : free-id-set?
Like in-set.

procedure

(free-id-set->stream s)  stream?

  s : free-id-set?

procedure

(free-id-set->list s)  list?

  s : free-id-set?
Like set->list.

procedure

(free-id-set-copy s)  free-id-set?

  s : free-id-set?
Like set-copy.

procedure

(free-id-set-copy-clear s)  free-id-set?

  s : free-id-set?

Like set-clear.

procedure

(free-id-set-clear! s)  void?

  s : mutable-free-id-set?

procedure

(free-id-set-union s0 s ...)  immutable-free-id-set?

  s0 : immutable-free-id-set?
  s : free-id-set?
Like set-union.

procedure

(free-id-set-union! s0 s ...)  void?

  s0 : mutable-free-id-set?
  s : free-id-set?

procedure

(free-id-set-intersect! s0 s ...)  void?

  s0 : mutable-free-id-set?
  s : free-id-set?

procedure

(free-id-set-subtract s0 s ...)  immutable-free-id-set?

  s0 : immutable-free-id-set?
  s : free-id-set?

procedure

(free-id-set-subtract! s0 s ...)  void?

  s0 : mutable-free-id-set?
  s : free-id-set?

procedure

(free-id-set-symmetric-difference! s0 s ...)  void?

  s0 : mutable-free-id-set?
  s : free-id-set?

procedure

(free-id-subset? s1 s2)  boolean?

  s1 : free-id-set?
  s2 : free-id-set?
Like subset?.

procedure

(free-id-proper-subset? s1 s2)  boolean?

  s1 : free-id-set?
  s2 : free-id-set?

procedure

(free-id-set-map s f)  list?

  s : free-id-set?
  f : (-> identifier? any/c)
Like set-map.

procedure

(free-id-set-for-each s f)  void?

  s : free-id-set?
  f : (-> identifier? any/c)

procedure

(id-set/c elem-ctc    
  [#:setidtype idsettype    
  #:mutability mutability])  contract?
  elem-ctc : flat-contract?
  idsettype : (or/c 'dont-care 'free 'bound) = 'dont-care
  mutability : (or/c 'dont-care 'mutable 'immutable)
   = 'immutable
Creates a contract for identifier sets. If mutability is 'immutable, the contract accepts only immutable identifier sets; if mutability is 'mutable, the contract accepts only mutable identifier sets.

procedure

(free-id-set/c elem-ctc    
  [#:mutability mutability])  contract?
  elem-ctc : flat-contract?
  mutability : (or/c 'dont-care 'mutable 'immutable)
   = 'immutable
Creates a contract for free-identifier sets. If mutability is 'immutable, the contract accepts only immutable identifier sets; if mutability is 'mutable, the contract accepts only mutable identifier sets.

2.4.2 Sets for bound-identifier=?🔗

A bound-identifier set is a set whose keys are compared using bound-identifier=?. Bound-identifier sets implement the gen:set interface, so all of the appropriate generic functions (e.g., set-add, set-map, etc.) can be used on bound-identifier sets.

procedure

(mutable-bound-id-set [init-set    
  #:phase phase])  mutable-bound-id-set?
  init-set : set? = null
  phase : (or/c exact-integer? #f) = (syntax-local-phase-level)

procedure

(immutable-bound-id-set [init-set 
  #:phase phase]) 
  immutable-bound-id-set?
  init-set : set? = null
  phase : (or/c exact-integer? #f) = (syntax-local-phase-level)

procedure

(bound-id-set? v)  boolean?

  v : any/c

procedure

(mutable-bound-id-set? v)  boolean?

  v : any/c

procedure

(immutable-bound-id-set? v)  boolean?

  v : any/c

procedure

(bound-id-set-empty? s)  boolean?

  s : bound-id-set?

procedure

(bound-id-set-count s)  exact-nonnegative-integer?

  s : bound-id-set?

procedure

(bound-id-set-member? s v)  boolean?

  s : bound-id-set?
  v : identifier?

procedure

(bound-id-set=? s1 s2)  boolean?

  s1 : bound-id-set?
  s2 : bound-id-set?

procedure

(bound-id-set-add s v)  immutable-bound-id-set?

  s : immutable-bound-id-set?
  v : identifier?

procedure

(bound-id-set-add! s v)  void?

  s : mutable-bound-id-set?
  v : identifier?

procedure

(bound-id-set-remove s v)  immutable-bound-id-set?

  s : immutable-bound-id-set?
  v : identifier?

procedure

(bound-id-set-remove! s v)  void?

  s : mutable-bound-id-set?
  v : identifier?

procedure

(bound-id-set-first s)  identifier?

  s : bound-id-set?

procedure

(bound-id-set-rest s)  immutable-bound-id-set?

  s : immutable-bound-id-set?

procedure

(in-bound-id-set s)  sequence?

  s : bound-id-set?

procedure

(bound-id-set->stream s)  stream?

  s : bound-id-set?

procedure

(bound-id-set->list s)  list?

  s : bound-id-set?

procedure

(bound-id-set-copy s)  bound-id-set?

  s : bound-id-set?

procedure

(bound-id-set-copy-clear s)  bound-id-set?

  s : bound-id-set?

procedure

(bound-id-set-clear s)  immutable-bound-id-set?

  s : immutable-bound-id-set?

procedure

(bound-id-set-clear! s)  void?

  s : mutable-bound-id-set?

procedure

(bound-id-set-union s0 s ...)  immutable-bound-id-set?

  s0 : immutable-bound-id-set?
  s : bound-id-set?

procedure

(bound-id-set-union! s0 s ...)  void?

  s0 : mutable-bound-id-set?
  s : bound-id-set?

procedure

(bound-id-set-intersect s0 s ...)  immutable-bound-id-set?

  s0 : immutable-bound-id-set?
  s : bound-id-set?

procedure

(bound-id-set-intersect! s0 s ...)  void?

  s0 : mutable-bound-id-set?
  s : bound-id-set?

procedure

(bound-id-set-subtract s0 s ...)  immutable-bound-id-set?

  s0 : immutable-bound-id-set?
  s : bound-id-set?

procedure

(bound-id-set-subtract! s0 s ...)  void?

  s0 : mutable-bound-id-set?
  s : bound-id-set?

procedure

(bound-id-set-symmetric-difference s0 s ...)

  immutable-bound-id-set?
  s0 : immutable-bound-id-set?
  s : bound-id-set?

procedure

(bound-id-set-symmetric-difference! s0    
  s ...)  void?
  s0 : mutable-bound-id-set?
  s : bound-id-set?

procedure

(bound-id-subset? s1 s2)  boolean?

  s1 : bound-id-set?
  s2 : bound-id-set?

procedure

(bound-id-proper-subset? s1 s2)  boolean?

  s1 : bound-id-set?
  s2 : bound-id-set?

procedure

(bound-id-set-map s f)  list?

  s : bound-id-set?
  f : (-> identifier? any/c)

procedure

(bound-id-set-for-each s f)  void?

  s : bound-id-set?
  f : (-> identifier? any/c)

procedure

(bound-id-set/c elem-ctc    
  [#:mutability mutability])  contract?
  elem-ctc : flat-contract?
  mutability : (or/c 'dont-care 'mutable 'immutable)
   = 'immutable
Like the procedures for free-identifier sets (e.g., immutable-free-id-set, free-id-set-add, etc.), but for bound-identifier sets, which use bound-identifier=? to compare keys.

2.5 Hashing on bound-identifier=? and free-identifier=?🔗

This library is for backwards-compatibility. Do not use it for new libraries; use syntax/id-table instead.

 (require syntax/boundmap) package: base

procedure

(make-bound-identifier-mapping)  bound-identifier-mapping?

procedure

(bound-identifier-mapping? v)  boolean?

  v : any/c

procedure

(bound-identifier-mapping-get bound-map    
  id    
  [failure-thunk])  any
  bound-map : bound-identifier-mapping?
  id : identifier?
  failure-thunk : (-> any)
   = (lambda () (raise (make-exn:fail ....)))

procedure

(bound-identifier-mapping-put! bound-map    
  id    
  v)  void?
  bound-map : bound-identifier-mapping?
  id : identifier?
  v : any/c

procedure

(bound-identifier-mapping-for-each bound-map    
  proc)  void?
  bound-map : boud-identifier-mapping?
  proc : (identifier? any/c . -> . any)

procedure

(bound-identifier-mapping-map bound-map    
  proc)  (listof any?)
  bound-map : bound-identifier-mapping?
  proc : (identifier? any/c . -> . any)

procedure

(make-free-identifier-mapping)  free-identifier-mapping?

procedure

(free-identifier-mapping? v)  boolean?

  v : any/c

procedure

(free-identifier-mapping-get free-map    
  id    
  [failure-thunk])  any
  free-map : free-identifier-mapping?
  id : identifier?
  failure-thunk : (-> any)
   = (lambda () (raise (make-exn:fail ....)))

procedure

(free-identifier-mapping-put! free-map id v)  void?

  free-map : free-identifier-mapping?
  id : identifier?
  v : any/c

procedure

(free-identifier-mapping-for-each free-map    
  proc)  void?
  free-map : free-identifier-mapping?
  proc : (identifier? any/c . -> . any)

procedure

(free-identifier-mapping-map free-map proc)  (listof any?)

  free-map : free-identifier-mapping?
  proc : (identifier? any/c . -> . any)

procedure

(make-module-identifier-mapping)  module-identifier-mapping?

procedure

(module-identifier-mapping? v)  boolean?

  v : any/c

procedure

(module-identifier-mapping-get module-map    
  id    
  [failure-thunk])  any
  module-map : module-identifier-mapping?
  id : identifier?
  failure-thunk : (-> any)
   = (lambda () (raise (make-exn:fail ....)))

procedure

(module-identifier-mapping-put! module-map    
  id    
  v)  void?
  module-map : module-identifier-mapping?
  id : identifier?
  v : any/c

procedure

(module-identifier-mapping-for-each module-map    
  proc)  void?
  module-map : module-identifier-mapping?
  proc : (identifier? any/c . -> . any)

procedure

(module-identifier-mapping-map module-map    
  proc)  (listof any?)
  module-map : module-identifier-mapping?
  proc : (identifier? any/c . -> . any)

2.6 Rendering Syntax Objects with Formatting🔗

 (require syntax/to-string) package: base

procedure

(syntax->string stx-list)  string?

  stx-list : (and/c syntax? stx-list?)
Builds a string with newlines and indenting according to the source locations in stx-list; the outer pair of parens are not rendered from stx-list.

2.7 Computing the Free Variables of an Expression🔗

 (require syntax/free-vars) package: base

procedure

(free-vars expr-stx 
  [insp 
  #:module-bound? module-bound?]) 
  (listof identifier?)
  expr-stx : syntax?
  insp : inspector? = mod-decl-insp
  module-bound? : any/c = #f
Returns a list of free lambda- and let-bound identifiers in expr-stx in the order in which each identifier first appears within expr-stx. The expression must be fully expanded (see Fully Expanded Programs and expand).

The inspector insp is used to disarm expr-stx and sub-expressions before extracting identifiers. The default insp is the declaration-time inspector of the syntax/free-vars module.

If module-bound? is non-false, the list of free variables also includes free module-bound identifiers.

Examples:
> (require (for-syntax racket/base syntax/parse syntax/free-vars))
> (define-syntax (print-body-free-vars stx)
    (syntax-parse stx
      #:literals (lambda)
      [(_ (~and lam (lambda (a ...) b ...)))
       (define expanded-body (local-expand #'lam 'expression '()))
       (syntax-parse expanded-body
         #:literals (#%plain-lambda)
         [(#%plain-lambda (arg ...) body)
          (displayln (free-vars #'body))
          expanded-body])]))
> (lambda (x) (print-body-free-vars (lambda (y) x)))

(#<syntax:eval:3:0 x>)

#<procedure>

2.8 Replacing Lexical Context🔗

 (require syntax/strip-context) package: base

procedure

(strip-context form)  any/c

  form : any/c
Removes all lexical context from syntax objects within form, preserving source-location information and properties.

Typically, form is a syntax object, and then the result is also a syntax object. Otherwise, pairs, vectors, boxes, hash tables, and prefab structures are traversed (and copied for the result) to find syntax objects. Graph structure is not preserved in the result, and cyclic data structures will cause strip-context to never return.

Changed in version 7.7.0.10 of package base: Repaired to traverse hash tables in stx.

procedure

(replace-context ctx-stx form)  any/c

  ctx-stx : (or/c syntax? #f)
  form : any/c
Uses the lexical context of ctx-stx to replace the lexical context of all parts of all syntax objects in form, preserving source-location information and properties of those syntax objects.

Syntax objects are found in form the same as in strip-context.

Changed in version 7.7.0.10 of package base: Repaired to traverse hash tables in stx.

2.9 Helpers for Processing Keyword Syntax🔗

The syntax/keyword module contains procedures for parsing keyword options in macros.

 (require syntax/keyword) package: base

  keyword-table = (dict-of keyword (listof check-procedure))

A keyword-table is a dictionary (dict?) mapping keywords to lists of check-procedures. (Note that an association list is a suitable dictionary.) The keyword’s arity is the length of the list of procedures.

Example:
> (define my-keyword-table
    (list (list '#:a check-identifier)
          (list '#:b check-expression check-expression)))

  check-procedure = (syntax syntax -> any)

A check procedure consumes the syntax to check and a context syntax object for error reporting and either raises an error to reject the syntax or returns a value as its parsed representation.

Example:
> (define (check-stx-string stx context-stx)
    (unless (string? (syntax-e stx))
      (raise-syntax-error #f "expected string" context-stx stx))
    stx)

  options = (listof (list keyword syntax-keyword any ...))

Parsed options are represented as an list of option entries. Each entry contains the keyword, the syntax of the keyword (for error reporting), and the list of parsed values returned by the keyword’s list of check procedures. The list contains the parsed options in the order they appeared in the input, and a keyword that occurs multiple times in the input occurs multiple times in the options list.

procedure

(parse-keyword-options stx 
  table 
  [#:context ctx 
  #:no-duplicates? no-duplicates? 
  #:incompatible incompatible 
  #:on-incompatible incompatible-handler 
  #:on-too-short too-short-handler 
  #:on-not-in-table not-in-table-handler]) 
  
options any/c
  stx : syntax?
  table : keyword-table
  ctx : (or/c #f syntax?) = #f
  no-duplicates? : boolean? = #f
  incompatible : (listof (listof keyword?)) = '()
  incompatible-handler : 
(-> keyword? keyword?
    options syntax? syntax?
    (values options syntax?))
   = (lambda (....) (error ....))
  too-short-handler : 
(-> keyword? options syntax? syntax?
    (values options syntax?))
   = (lambda (....) (error ....))
  not-in-table-handler : 
(-> keyword? options syntax? syntax?
    (values options syntax?))
   = (lambda (....) (error ....))
Parses the keyword options in the syntax stx (stx may be an improper syntax list). The keyword options are described in the table association list. Each entry in table should be a list whose first element is a keyword and whose subsequent elements are procedures for checking the arguments following the keyword. The keyword’s arity (number of arguments) is determined by the number of procedures in the entry. Only fixed-arity keywords are supported.

Parsing stops normally when the syntax list does not have a keyword at its head (it may be empty, start with a non-keyword term, or it may be a non-list syntax object). Two values are returned: the parsed options and the rest of the syntax (generally either a syntax object or a list of syntax objects).

A variety of errors and exceptional conditions can occur during the parsing process. The following keyword arguments determine the behavior in those situations.

The #:context ctx argument is used to report all errors in parsing syntax. In addition, ctx is passed as the final argument to all provided handler procedures. Macros using parse-keyword-options should generally pass the syntax object for the whole macro use as ctx.

If no-duplicates? is a non-false value, then duplicate keyword options are not allowed. If a duplicate is seen, the keyword’s associated check procedures are not called and an incompatibility is reported.

The incompatible argument is a list of incompatibility entries, where each entry is a list of at least two keywords. If any keyword in the entry occurs after any other keyword in the entry, an incompatibility is reported.

Note that including a keyword in an incompatibility entry does not prevent it from occurring multiple times. To disallow duplicates of some keywords (as opposed to all keywords), include those keywords in the incompatible list as being incompatible with themselves. That is, include them twice:

; Disallow duplicates of only the #:foo keyword
(parse-keyword-options .... #:incompatible '((#:foo #:foo)))

When an incompatibility occurs, the incompatible-handler is tail-called with the two keywords causing the incompatibility (in the order that they occurred in the syntax list, so the keyword triggering the incompatibility occurs second), the syntax list starting with the occurrence of the second keyword, and the context (ctx). If the incompatibility is due to a duplicate, the two keywords are the same.

When a keyword is not followed by enough arguments according to its arity in table, the too-short-handler is tail-called with the keyword, the options parsed thus far, the syntax list starting with the occurrence of the keyword, and ctx.

When a keyword occurs in the syntax list that is not in table, the not-in-table-handler is tail-called with the keyword, the options parsed thus far, the syntax list starting with the occurrence of the keyword, and ctx.

Handlers typically escape—all of the default handlers raise errors—but if they return, they should return two values: the parsed options and a syntax object; these are returned as the results of parse-keyword-options.

Examples:
> (parse-keyword-options
   #'(#:transparent #:property p (lambda (x) (f x)))
   (list (list '#:transparent)
         (list '#:inspector check-expression)
         (list '#:property check-expression check-expression)))

'((#:transparent #<syntax:eval:4:0 #:transparent>)

  (#:property

   #<syntax:eval:4:0 #:property>

   #<syntax:eval:4:0 p>

   #<syntax:eval:4:0 (lambda (x) (f x))>))

'()

> (parse-keyword-options
   #'(#:transparent #:inspector (make-inspector))
   (list (list '#:transparent)
         (list '#:inspector check-expression)
         (list '#:property check-expression check-expression))
   #:context #'define-struct
   #:incompatible '((#:transparent #:inspector)
                    (#:inspector #:inspector)
                    (#:inspector #:inspector)))

define-struct: #:inspector option not allowed after

#:transparent option

procedure

(parse-keyword-options/eol 
  stx 
  table 
  [#:context ctx 
  #:no-duplicates? no-duplicates? 
  #:incompatible incompatible 
  #:on-incompatible incompatible-handler 
  #:on-too-short too-short-handler 
  #:on-not-in-table not-in-table-handler 
  #:on-not-eol not-eol-handler]) 
  options
  stx : syntax?
  table : keyword-table
  ctx : (or/c #f syntax?) = #f
  no-duplicates? : boolean? = #f
  incompatible : (listof (list keyword? keyword?)) = '()
  incompatible-handler : 
(-> keyword? keyword?
    options syntax? syntax?
    (values options syntax?))
   = (lambda (....) (error ....))
  too-short-handler : 
(-> keyword? options syntax? syntax?
    (values options syntax?))
   = (lambda (....) (error ....))
  not-in-table-handler : 
(-> keyword? options syntax? syntax?
    (values options syntax?))
   = (lambda (....) (error ....))
  not-eol-handler : 
(-> options syntax? syntax?
    options)
   = (lambda (....) (error ....))
Like parse-keyword-options, but checks that there are no terms left over after parsing all of the keyword options. If there are, not-eol-handler is tail-called with the options parsed thus far, the leftover syntax, and ctx.

procedure

(options-select options keyword)  (listof list?)

  options : options
  keyword : keyword?
Selects the values associated with one keyword from the parsed options. The resulting list has as many items as there were occurrences of the keyword, and each element is a list whose length is the arity of the keyword.

procedure

(options-select-row options    
  keyword    
  #:default default)  any
  options : options
  keyword : keyword?
  default : any/c
Like options-select, except that the given keyword must occur either zero or one times in options. If the keyword occurs, the associated list of parsed argument values is returned. Otherwise, the default list is returned.

procedure

(options-select-value options    
  keyword    
  #:default default)  any
  options : options
  keyword : keyword?
  default : any/c
Like options-select, except that the given keyword must occur either zero or one times in options. If the keyword occurs, the associated list of parsed argument values must have exactly one element, and that element is returned. If the keyword does not occur in options, the default value is returned.

procedure

(check-identifier stx ctx)  identifier?

  stx : syntax?
  ctx : (or/c #f syntax?)
A check-procedure that accepts only identifiers.

procedure

(check-expression stx ctx)  syntax?

  stx : syntax?
  ctx : (or/c #f syntax?)
A check-procedure that accepts any non-keyword term. It does not actually check that the term is a valid expression.

procedure

((check-stx-listof check) stx ctx)  (listof any/c)

  check : check-procedure
  stx : syntax?
  ctx : (or/c #f syntax?)
Lifts a check-procedure to accept syntax lists of whatever the original procedure accepted.

procedure

(check-stx-string stx ctx)  syntax?

  stx : syntax?
  ctx : (or/c #f syntax?)
A check-procedure that accepts syntax strings.

procedure

(check-stx-boolean stx ctx)  syntax?

  stx : syntax?
  ctx : (or/c #f syntax?)
A check-procedure that accepts syntax booleans.