2 Syntax Object Helpers
2.1 Deconstructing Syntax Objects
(require syntax/stx) | package: base |
> (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
> (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
proc : procedure? stxl : stx-list?
> (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?
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 ...)
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 ...)
syntax
(kernel-syntax-case/phase stx-expr phase-expr clause ...)
syntax
(kernel-syntax-case*/phase stx-expr phase-expr (extra-id ..) clause ...)
procedure
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)
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
procedure
v : any/c
procedure
v : any/c
procedure
(free-id-table-ref table id [failure]) → any
table : free-id-table? id : identifier? failure : any/c = (lambda () (raise (make-exn:fail .....)))
procedure
(free-id-table-ref! table id failure) → any
table : mutable-free-id-table? id : identifier? failure : any/c
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
procedure
(free-id-table-set table id v) → immutable-free-id-table?
table : immutable-free-id-table? id : identifier? v : any/c
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
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)
procedure
(free-id-table-keys table) → (listof identifier?)
table : free-id-table?
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?
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
table : free-id-table?
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
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
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.
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)
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
procedure
(mutable-free-id-set? v) → boolean?
v : any/c
procedure
v : any/c
procedure
(free-id-set-empty? s) → boolean?
s : free-id-set?
procedure
s : free-id-set?
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?
procedure
s : immutable-free-id-set? v : identifier?
procedure
(free-id-set-add! s v) → void?
s : mutable-free-id-set? v : identifier?
procedure
s : immutable-free-id-set? v : identifier?
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?
procedure
s : immutable-free-id-set?
procedure
(in-free-id-set s) → sequence?
s : free-id-set?
procedure
(free-id-set->stream s) → stream?
s : free-id-set?
procedure
(free-id-set->list s) → list?
s : free-id-set?
procedure
(free-id-set-copy s) → free-id-set?
s : free-id-set?
procedure
s : free-id-set?
procedure
s : immutable-free-id-set?
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?
procedure
(free-id-set-union! s0 s ...) → void?
s0 : mutable-free-id-set? s : free-id-set?
procedure
(free-id-set-intersect s0 s ...) → immutable-free-id-set?
s0 : immutable-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 ...)
→ immutable-free-id-set? s0 : immutable-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?
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)
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
procedure
(free-id-set/c elem-ctc [ #:mutability mutability]) → contract? elem-ctc : flat-contract?
mutability : (or/c 'dont-care 'mutable 'immutable) = 'immutable
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
v : any/c
procedure
v : any/c
procedure
(bound-id-set-empty? s) → boolean?
s : bound-id-set?
procedure
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
s : immutable-bound-id-set? v : identifier?
procedure
(bound-id-set-add! s v) → void?
s : mutable-bound-id-set? v : identifier?
procedure
s : immutable-bound-id-set? v : identifier?
procedure
(bound-id-set-remove! s v) → void?
s : mutable-bound-id-set? v : identifier?
procedure
s : bound-id-set?
procedure
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
s : bound-id-set?
procedure
s : bound-id-set?
procedure
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
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
procedure
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 : bound-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
procedure
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
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?)
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
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.
> (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
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
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.
> (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.
> (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 ....))
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—
> (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 ....))
procedure
(options-select options keyword) → (listof list?)
options : options keyword : keyword?
procedure
(options-select-row options keyword #:default default) → any options : options keyword : keyword? default : any/c
procedure
(options-select-value options keyword #:default default) → any options : options keyword : keyword? default : any/c
procedure
(check-identifier stx ctx) → identifier?
stx : syntax? ctx : (or/c #f syntax?)
procedure
(check-expression stx ctx) → syntax?
stx : syntax? ctx : (or/c #f syntax?)
procedure
((check-stx-listof check) stx ctx) → (listof any/c)
check : check-procedure stx : syntax? ctx : (or/c #f syntax?)
procedure
(check-stx-string stx ctx) → syntax?
stx : syntax? ctx : (or/c #f syntax?)
procedure
(check-stx-boolean stx ctx) → syntax?
stx : syntax? ctx : (or/c #f syntax?)