Before Guile 2.0, lambda*
and define*
were implemented
using macros that processed rest list arguments. This was not optimal,
as calling procedures with optional arguments had to allocate rest
lists at every procedure invocation. Guile 2.0 improved this
situation by bringing optional and keyword arguments into Guile’s
core.
However there are occasions in which you have a list and want to parse
it for optional or keyword arguments. Guile’s (ice-9 optargs)
provides some macros to help with that task.
The syntax let-optional
and let-optional*
are for
destructuring rest argument lists and giving names to the various list
elements. let-optional
binds all variables simultaneously, while
let-optional*
binds them sequentially, consistent with let
and let*
(see Local Variable Bindings).
These two macros give you an optional argument interface that is very
Schemey and introduces no fancy syntax. They are compatible with
the scsh macros of the same name, but are slightly extended. Each of
binding may be of one of the forms var or (var
default-value)
. rest-arg should be the rest-argument of the
procedures these are used from. The items in rest-arg are
sequentially bound to the variable names are given. When rest-arg
runs out, the remaining vars are bound either to the default values or
#f
if no default value was specified. rest-arg remains
bound to whatever may have been left of rest-arg.
After binding the variables, the expressions body1 body2 … are evaluated in order.
Similarly, 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 body1
body2 … 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.
(ice-9 optargs)
also provides some more define*
sugar,
which is not so useful with modern Guile coding, but still supported:
define*-public
is the lambda*
version of
define-public
; defmacro*
and defmacro*-public
exist for defining macros with the improved argument list handling
possibilities. The -public
versions not only define the
procedures/macros, but also export them from the current module.
Like a mix of define*
and define-public
.
These are just like defmacro
and defmacro-public
except that they
take lambda*
-style extended parameter lists, where #:optional
,
#:key
, #:allow-other-keys
and #:rest
are allowed with the usual
semantics. Here is an example of a macro with an optional argument:
(defmacro* transmogrify (a #:optional b) (a 1))