6.7.4.1 lambda* and define*.

lambda* is like lambda, except with some extensions to allow optional and keyword arguments.

library syntax: lambda* ([var…]
[#:optional vardef…]
[#:key vardef… [#:allow-other-keys]]
[#:rest var | . var])
body1 body2 …

Create a procedure which takes optional and/or keyword arguments specified with #:optional and #:key. For example,

(lambda* (a b #:optional c d . e) '())

is a procedure with fixed arguments a and b, optional arguments c and d, and rest argument e. If the optional arguments are omitted in a call, the variables for them are bound to #f.

Likewise, define* is syntactic sugar for defining procedures using lambda*.

lambda* can also make procedures with keyword arguments. For example, a procedure defined like this:

(define* (sir-yes-sir #:key action how-high)
  (list action how-high))

can be called as (sir-yes-sir #:action 'jump), (sir-yes-sir #:how-high 13), (sir-yes-sir #:action 'lay-down #:how-high 0), or just (sir-yes-sir). Whichever arguments are given as keywords are bound to values (and those not given are #f).

Optional and keyword arguments can also have default values to take when not present in a call, by giving a two-element list of variable name and expression. For example in

(define* (frob foo #:optional (bar 42) #:key (baz 73))
  (list foo bar baz))

foo is a fixed argument, bar is an optional argument with default value 42, and baz is a keyword argument with default value 73. Default value expressions are not evaluated unless they are needed, and until the procedure is called.

Normally it’s an error if a call has keywords other than those specified by #:key, but adding #:allow-other-keys to the definition (after the keyword argument declarations) will ignore unknown keywords.

If a call has a keyword given twice, the last value is used. For example,

(define* (flips #:key (heads 0) (tails 0))
  (display (list heads tails)))

(flips #:heads 37 #:tails 42 #:heads 99)
-| (99 42)

#:rest is a synonym for the dotted syntax rest argument. The argument lists (a . b) and (a #:rest b) are equivalent in all respects. This is provided for more similarity to DSSSL, MIT-Scheme and Kawa among others, as well as for refugees from other Lisp dialects.

When #:key is used together with a rest argument, the keyword parameters in a call all remain in the rest list. This is the same as Common Lisp. For example,

((lambda* (#:key (x 0) #:allow-other-keys #:rest r)
   (display r))
 #:x 123 #:y 456)
-| (#:x 123 #:y 456)

#:optional and #:key establish their bindings successively, from left to right. This means default expressions can refer back to prior parameters, for example

(lambda* (start #:optional (end (+ 10 start)))
  (do ((i start (1+ i)))
      ((> i end))
    (display i)))

The exception to this left-to-right scoping rule is the rest argument. If there is a rest argument, it is bound after the optional arguments, but before the keyword arguments.