[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.15.1.3 Optional argument parsing

To have optional arguments or keyword arguments in Scheme, you have to take variable arguments as a list and decompose them by yourself. The following macros help it.

Macro: let-optionals* restargs (var-spec ...) body ...
Macro: let-optionals* restargs (var-spec ... . restvar) body ...
Given a list of values restargs, binds variables accodring to var-spec, then evaluates body.

Var-spec can be either a symbol, or a list of two elements and its car is a symbol. The symbol is the bound variable name. The values in restargs are bound to the symbol in order. If there are not as many values in restargs as var-spec, the rest of symbols are bound to the default values, determined as follows: If var-spec is just a symbol, the default value is undefined. If var-spec is a list, the default value is the result of evaluation of the second element of the list. In the latter case the second element is only evaluated when there are not enough arguments. The binding proceeds in the order of var-spec, so the second element may refer to the bindings of previous var-spec.

In the second form, restvar must be a symbol and bound to the list of values whatever left from restargs after binding to var-spec.

It is not an error if restarg has more values than var-specs. The extra values are simply ignored in the first form.

 
(define (proc x . args)
  (let-optionals* args ((a 'a)
                        (b 'b)
                        (c 'c))
    (list x a b c)))

(proc 0)         => (0 a b c)
(proc 0 1)       => (0 1 b c)
(proc 0 1 2)     => (0 1 2 c)
(proc 0 1 2 3)   => (0 1 2 3)

(define (proc2 . args)
  (let-optionals* args ((a 'a) . b)
    (list a b)))

(proc2)          => (a ())
(proc2 0)        => (0 ())
(proc2 0 1)      => (0 (1))
(proc2 0 1 2)    => (0 (1 2))

(define (proc3 . args)
  (let-optionals* args ((a 0)
                        (b (+ a 1))
                        (c (+ b 1)))
    (list a b c)))

(proc3)          => (0 1 2)
(proc3 8)        => (8 9 10)
(proc3 8 2)      => (8 2 3)
(proc3 8 2 -1)   => (8 2 -1)

Macro: get-optional restargs default
This is a short version of let-optionals* where you have only one optional argument. Given the optional argument list restargs, this macro returns the value of optional argument if one is given, or the result of default otherwise. Default is not evaluated unless restargs is an empty list.

 
(define (proc x . maybe-opt)
  (let ((option (get-optional maybe-opt #f)))
    (list x option)))

(proc 0)         => (0 #f)
(proc 0 1)       => (0 1)

Macro: let-keywords* restarg (var-spec ...) body ...
This macro is for keyword arguments. Var-spec can be one of the following forms:

(symbol expr)
If the restrag contains keyword which has the same name as symbol, binds symbol to the corresponding value. If such a keyword doesn't appear in restarg, binds symbol to the result of expr.
(symbol keyword expr)
If the restrag contains keyword keyword, binds symbol to the corresponding value. If such a keyword doesn't appear in restarg, binds symbol to the result of expr.

The default value expr is only evaluated when the keyword is not given to the restarg. The binding is done in the order of var-spec, so the expr can refer to the variables bound by preceding var-spec.

If a keyword that doesn't listed in var-spec appears in restarg, it is simply ignored.

 
(define (proc x . options)
  (let-keywords* options ((a 'a)
                          (b :beta 'b)
                          (c 'c))
    (list x a b c)))

(proc 0)         => (0 a b c)
(proc 0 :a 1)    => (0 1 b c)
(proc 0 :beta 1) => (0 a 1 c)
(proc 0 :beta 1 :c 3) => (0 a 1 3)


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated by Ken Dickey on November, 28 2002 using texi2html