Next: , Previous: let-optional Reference, Up: Optional Arguments let-keywords Reference

let-keywords and let-keywords* extract values from keyword style argument lists, binding local variables to those values or to defaults.

— library syntax: let-keywords args allow-other-keys? (binding ...) body ...
— library syntax: let-keywords* args allow-other-keys? (binding ...) body ...

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 foo comes from the #:foo keyword in args. But the binding for bar is the default in the let-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 like 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-keywords.

let-keywords* is like 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