let-keywords* extract values from
keyword style argument lists, binding local variables to those values
or to defaults.
args is evaluated and should give a list of the form
(#:keyword1 value1 #:keyword2 value2 ...). The bindings are variables and default expressions, with the variables to be set (by name) from the keyword values. The body forms are then evaluated and the last is the result. An example will make the syntax clearest,(define args '(#:xyzzy "hello" #:foo "world")) (let-keywords args #t ((foo "default for foo") (bar (string-append "default" "for" "bar"))) (display foo) (display ", ") (display bar)) -| world, defaultforbar
The binding for
foocomes from the
args. But the binding for
baris the default in the
let-keywords, since there's no
#:barin the args.
allow-other-keys? is evaluated and controls whether unknown keywords are allowed in the args list. When true other keys are ignored (such as
#:xyzzyin the example), when
#fan error is thrown for anything unknown.
let(see Local Bindings) in that all bindings are made at once, the defaults expressions are evaluated (if needed) outside the scope of the
let*, each binding is made successively, and the default expressions see the bindings previously made. This is the style used by
lambda*keywords (see lambda* Reference). For example,(define args '(#:foo 3)) (let-keywords* args #f ((foo 99) (bar (+ foo 6))) (display bar)) -| 9
The expression for each default is only evaluated if it's needed, ie. if the keyword doesn't appear in args. So one way to make a keyword mandatory is to throw an error of some sort as the default.(define args '(#:start 7 #:finish 13)) (let-keywords* args #t ((start 0) (stop (error "missing #:stop argument"))) ...) ⇒ ERROR: missing #:stop argument