12.3 Syntax Object Bindings

► |  | The Racket Reference

1 | Language Model
2 | Notation for Documentation
3 | Syntactic Forms
4 | Datatypes
5 | Structures
6 | Classes and Objects
7 | Units
8 | Contracts
9 | Pattern Matching
10 | Control Flow
11 | Concurrency and Parallelism
12 | Macros
13 | Input and Output
14 | Reflection and Security
15 | Operating System
16 | Memory Management
17 | Unsafe Operations
18 | Running Racket
| Bibliography
| Index

▼ | 12 | Macros

12.1 | Pattern-Based Syntax Matching
12.2 | Syntax Object Content
12.3 | Syntax Object Bindings
12.4 | Syntax Transformers
12.5 | Syntax Parameters
12.6 | Local Binding with Splicing Body
12.7 | Syntax Object Properties
12.8 | Syntax Taints
12.9 | Expanding Top-Level Forms
12.10 | Serializing Syntax
12.11 | File Inclusion
12.12 | Syntax Utilities
12.13 | Phase and Space Utilities

On this page:

bound-identifier=?
free-identifier=?
free-transformer-identifier=?
free-template-identifier=?
free-label-identifier=?
check-duplicate-identifier
identifier-binding
identifier-transformer-binding
identifier-template-binding
identifier-label-binding
identifier-distinct-binding
identifier-binding-symbol
identifier-binding-portal-syntax
syntax-bound-symbols
syntax-bound-interned-scope-symbols
syntax-bound-phases

Racket
top contents ← prev up next →

### 12.3 Syntax Object Bindings🔗ℹ

> procedure (bound-identifier=? a-id b-id [phase-level]) → boolean?
> a-id : syntax?
> b-id : syntax?
> | phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)

Returns #t if the identifier a-id would bind b-id (or vice versa) if the identifiers were substituted in a suitable expression context at the phase level indicated by phase-level, #f otherwise. A #f value for phase-level corresponds to the label phase level.

Examples:

> > (define-syntax (check stx)
> (syntax-case stx ()
> [(_ x y)
> (if (bound-identifier=? #'x #'y)
> #'(let ([y 'wrong]) (let ([x 'binds]) y))
> #'(let ([y 'no-binds]) (let ([x 'wrong]) y)))]))
> > (check a a)
> 'binds
> > (check a b)
> 'no-binds
> > (define-syntax-rule (check-a x) (check a x))
> > (check-a a)
> 'no-binds

> > procedure
> > (free-identifier=? |  | a-id |  |  |  |
> > |  | b-id |  |  |  |
> > | [ | a-phase-level |  |  |  |
> > |  | b-phase-level]) |  | → |  | boolean?
> a-id : identifier?
> b-id : identifier?
> | a-phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)
> b-phase-level : (or/c exact-integer? #f) = a-phase-level

Returns #t if a-id and b-id access the same local binding, module binding, or top-level binding—perhaps via rename transformers—at the phase levels indicated by a-phase-level and b-phase-level, respectively. A #f value for a-phase-level or b-phase-level corresponds to the label phase level.

“Same module binding” means that the identifiers refer to the same original definition site, and not necessarily to the same require or provide site. Due to renaming in require and provide, or due to a transformer binding to a rename transformer, the identifiers may return distinct results with syntax-e.

Examples:

> > (define-syntax (check stx)
> (syntax-case stx ()
> [(_ x)
> (if (free-identifier=? #'car #'x)
> #'(list 'same: x)
> #'(list 'different: x))]))
> > (check car)
> '(same: #<procedure:car>)
> > (check mcar)
> '(different: #<procedure:mcar>)
> > (let ([car list])
> (check car))
> '(different: #<procedure:list>)
> > (require (rename-in racket/base [car kar]))
> > (check kar)
> '(same: #<procedure:car>)

> procedure (free-transformer-identifier=? a-id b-id) → boolean?
> a-id : identifier?
> b-id : identifier?

Same as (free-identifier=? a-id b-id (add1 (syntax-local-phase-level))).

> procedure (free-template-identifier=? a-id b-id) → boolean?
> a-id : identifier?
> b-id : identifier?

Same as (free-identifier=? a-id b-id (sub1 (syntax-local-phase-level))).

> procedure (free-label-identifier=? a-id b-id) → boolean?
> a-id : identifier?
> b-id : identifier?

Same as (free-identifier=? a-id b-id #f).

> procedure (check-duplicate-identifier ids) → (or/c identifier? #f)
> ids : (listof identifier?)

Compares each identifier in ids with every other identifier in the list with bound-identifier=?. If any comparison returns #t, one of the duplicate identifiers is returned (the first one in ids that is a duplicate), otherwise the result is #f.

> > procedure
> > (identifier-binding |  | id-stx |
> > | [ | phase-level |
> > |  | top-level-symbol? |
> > |  | exact-scopes?]) |
> | → |  |
> (or/c 'lexical
> #f
> (list/c module-path-index?
> symbol?
> module-path-index?
> symbol?
> exact-nonnegative-integer?
> phase+space-shift?
> phase+space?)
> (list/c symbol?))
> id-stx : identifier?
> | phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)
> top-level-symbol? : any/c = #f
> exact-scopes? : any/c = #f

Returns one of three (if top-level-symbol? is #f) or four (if top-level-symbol? is true) kinds of values, depending on the binding of id-stx at the phase level indicated by phase-level (where a #f value for phase-level corresponds to the label phase level):

- The result is 'lexical if id-stx has a local binding.

- The result is a list of seven items when id-stx has a module binding: (list from-mod from-sym nominal-from-mod nominal-from-sym from-phase import-phase+space-shift nominal-export-phase).

  - from-mod is a module path index (see Compiled Modules and References) that indicates the defining module. It is the “self” module path index if the binding refers to a definition in the enclosing module of id-stx.

  - from-sym is a symbol for the identifier’s name at its definition site in the originating module. This can be different from the local name returned by syntax->datum for several reasons: the identifier is renamed on import, it is renamed on export, or it is implicitly renamed because the binding site was generated by a macro invocation. In that last case, it may be an unreadable symbol, and it may be different from the result of syntax->datum on the identifier in the original source definition.

  - nominal-from-mod is a module path index (see Compiled Modules and References) that indicates the binding’s module as it appears locally in the source around id-stx: it indicates a module required into the context of id-stx to provide its binding, or it is the same “self” as from-mod for a binding that refers to a definition in the enclosing module of id-stx. It can be different from from-mod due to a re-export in nominal-from-mod of some imported identifier. If the same binding is imported in multiple ways, an arbitrary representative is chosen.

  - nominal-from-sym is a symbol for the binding’s identifier as it appears locally in the source around id-stx: it is the identifier’s name as exported by nominal-from-mod, or it is the source identifier’s symbol for a definition within the enclosing module of id-stx. It can be different from from-sym due to a renaming provide, even if from-mod and nominal-from-mod are the same, or due to a definition that was introduced by a macro expansion.

  - from-phase is an exact non-negative integer representing the originating phase. For example, it is 1 if the definition is for-syntax.

  - import-phase+space-shift is 0 if the binding import of nominal-from-mode is from a definition or a plain require, 1 if it is from a for-syntax import, a phase combined with a space name if it is from a for-space import, etc.

  - nominal-export-phase+space is the phase level and binding space of the export from nominal-from-mod for an imported binding, or it is the phase level of the definition for a binding from the enclosing module of id-stx.

- The result is (list top-sym) if id-stx has a top-level binding and top-level-symbol? is true. The top-sym can be different from the name returned by syntax->datum when the binding definition was generated by a macro invocation.

- The result is #f if id-stx has a top-level binding and top-level-symbol? is #f or if id-stx is unbound. An unbound identifier is typically treated the same as an identifier whose top-level binding is a variable.

If id-stx is bound to a rename-transformer, the result from identifier-binding is for the identifier in the transformer, so that identifier-binding is consistent with free-identifier=?.

If exact-scopes? is a true value, then the result is #f unless the binding for id-stx has exactly the scopes of id-stx. An exact-scopes check is useful for detecting whether an identifier is already bound in a specific definition context, for example.

Changed in version 6.6.0.4 of package base: Added the top-level-symbol? argument to report information on top-level bindings.
Changed in version 8.2.0.3: Generalized phase results to phase–space combinations.
Changed in version 8.6.0.9: Added the exact-scopes? argument.

> > procedure
> > (identifier-transformer-binding |  | id-stx |
> > | [ | rt-phase-level]) |
> | → |  |
> (or/c 'lexical
> #f
> (listof module-path-index?
> symbol?
> module-path-index?
> symbol?
> exact-nonnegative-integer?
> phase+space-shift?
> phase+space?))
> id-stx : identifier?
> | rt-phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)

Same as (identifier-binding id-stx (and rt-phase-level (add1 rt-phase-level))).

Changed in version 8.2.0.3 of package base: Generalized phase results to phase–space combinations.

> procedure (identifier-template-binding id-stx)
> | → |  |
> (or/c 'lexical
> #f
> (listof module-path-index?
> symbol?
> module-path-index?
> symbol?
> phase+space?
> phase+space-shift?
> phase+space?))
> id-stx : identifier?

Same as (identifier-binding id-stx (sub1 (syntax-local-phase-level))).

Changed in version 8.2.0.3 of package base: Generalized phase results to phase–space combinations.

> procedure (identifier-label-binding id-stx)
> | → |  |
> (or/c 'lexical
> #f
> (listof module-path-index?
> symbol?
> module-path-index?
> symbol?
> exact-nonnegative-integer?
> phase+space-shift?
> phase+space?))
> id-stx : identifier?

Same as (identifier-binding id-stx #f).

Changed in version 8.2.0.3 of package base: Generalized phase results to phase–space combinations.

> > procedure
> > (identifier-distinct-binding |  | id-stx |
> > |  | wrt-id-stx |
> > | [ | phase-level |
> > |  | top-level-symbol?]) |
> | → |  |
> (or/c 'lexical
> #f
> (list/c module-path-index?
> symbol?
> module-path-index?
> symbol?
> exact-nonnegative-integer?
> phase+space-shift?
> phase+space?)
> (list/c symbol?))
> id-stx : identifier?
> wrt-id-stx : identifier?
> | phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)
> top-level-symbol? : any/c = #f

Like (identifier-binding id-stx phase-level top-level-symbol?), but the result is #f if the binding for id-stx has scopes that are a subset of the scopes for wrt-id-stx. That is, if id-stx and wrt-id-stx have the same symbolic name, a binding for id-stx is returned only if the binding does not also apply to wrt-id-stx.

Added in version 8.3.0.8 of package base.
Changed in version 8.8.0.2: Added the top-level-symbol? argument.

> > procedure
> > (identifier-binding-symbol |  | id-stx |  |  |  |
> > | [ | phase-level]) |  | → |  | symbol?
> id-stx : identifier?
> | phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)

Like identifier-binding, but produces a symbol that corresponds to the binding. The symbol result is the same for any identifiers that are free-identifier=?, but the result may also be the same for identifiers that are not free-identifier=? (i.e., different symbols imply different bindings, but the same symbol does not imply the same binding).

When identifier-binding would produce a list, then the second element of that list is the result that identifier-binding-symbol produces.

> > procedure
> > (identifier-binding-portal-syntax |  | id-stx |
> > | [ | phase-level]) |
> → (or/c #f syntax?)
> id-stx : identifier?
> | phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)

If id-stx is bound at phase-level to portal syntax, either via define-syntax or #%require, then the portal syntax content is returned. The module that binds id-stx must be declared, but it need not be instantiated at the relevant phase, and identifier-binding-portal-syntax does not instantiate the module.

Added in version 8.3.0.8 of package base.

> > procedure
> > (syntax-bound-symbols |  | stx |  |  |  |
> > | [ | phase-level |  |  |  |
> > |  | exact-scopes?]) |  | → |  | (listof symbol?)
> stx : syntax?
> | phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)
> exact-scopes? : any/c = #f

Returns a list of all interned symbols for which (identifier-binding (datum->syntax stx sym) phase-level #f exact-scopes?) would produce a non-#f value. This procedure takes time proportional to the number of scopes on stx plus the length of the result list.

Added in version 8.6.0.6 of package base.
Changed in version 8.6.0.9: Added the exact-scopes? argument.

> > procedure
> > (syntax-bound-interned-scope-symbols |  | stx |
> > | [ | phase-level |
> > |  | exact-scopes?]) |
> → (listof symbol?)
> stx : syntax?
> | phase-level |  | : |  | (or/c exact-integer? #f)
> |  |  | = |  | (syntax-local-phase-level)
> exact-scopes? : any/c = #f

Returns a list of sym names of interned scopes for which (identifier-binding ((make-interned-syntax-introducer sym) stx) phase-level #f exact-scopes?) could produce a non-#f value. This procedure takes time proportional to the number of scopes on stx plus the length of the result list.

Added in version 8.13.0.8 of package base.

> procedure (syntax-bound-phases stx) → (listof (or/c exact-integer? #f))
> stx : syntax?

Returns a list that includes all phase-levels for which (syntax-bound-symbols stx phase-level) might produce a non-empty list.

Examples:

> > (syntax-bound-phases #'anything)
> '(2 1 0)
> > (require (for-meta 8 racket/base))
> > (syntax-bound-phases #'anything)
> '(9 8 2 1 0)

Added in version 8.6.0.8 of package base.

top contents ← prev up next →