let-keywords
and 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, defaultforbarThe binding for
foo
comes from the#:foo
keyword inargs
. But the binding forbar
is the default in thelet-keywords
, since there's no#:bar
in 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
#:xyzzy
in the example), when#f
an error is thrown for anything unknown.
let-keywords
is likelet
(see Local Bindings) in that all bindings are made at once, the defaults expressions are evaluated (if needed) outside the scope of thelet-keywords
.
let-keywords*
is likelet*
, each binding is made successively, and the default expressions see the bindings previously made. This is the style used bylambda*
keywords (see lambda* Reference). For example,(define args '(#:foo 3)) (let-keywords* args #f ((foo 99) (bar (+ foo 6))) (display bar)) -| 9The 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