Syntax to support optional and named keyword arguments.
let-optionals[*] is originally from SCSH, and
let-keywords[*] derived from Gauche.
let. The vars are
bound to fresh locations holding values taken in order from the
list ls, body is evaluated in the resulting
environment, and the value(s) of the last expression of body
returned. If the length of ls is shorter than the number of
vars, then the remaining vars taken their values from
their corresponding defaults, evaluated in an unspecified
order. Unused defaults are not evaluated. If a final
rest var is specified, then it is bound to any remaining
elements of ls beyond the length of ls, otherwise any
extra values are unused.
Typically used on the dotted rest list at the start of a lambda,
let-optionals is more concise and more efficient than
case-lambda for simple optional argument uses.
Example:
(define (copy-port . o)
(let-optionals o ((in (current-input-port))
(out (current-output-port))
(n-bytes #f))
(do ((i 0 (+ i 1))
(n (read-u8 in) (read-u8 in)))
((or (and n-bytes (>= i n-bytes))
(eof-object? b)))
(write-u8 b out)))
Example:
(let-optionals '(0) ((a 10) (b 11) (c 12))
(list a b c))=> (0 11 12)let* equivalent to let-optionals. Any required
default values are evaluated in left-to-right order, with
all preceding vars in scope.
Shorthand for
(lambda (required ... . o)
(let-optionals o ((var default) ... [rest])
body ...))
Shorthand for
(define name (opt-lambda (var default) ... [rest]) body ...)
Search for the identifier key in the list ls, treating
it as a property list of the form (key1 val1 key2 val2
...), and return the associated val. If not found, return
default, or #f.
Macro equivalent of keyword-ref, where default is
only evaluated if key is not found.
Analogous to let-optionals, except instead of binding the
vars by position they are bound by name, by searching in
ls with keyword-ref*. If an optional keyword
argument is provided it must be an identifier to use as the name,
otherwise var is used, appending a ":" (colon). If the name
is not found, var is bound to default, even if unused
names remain in ls.
If an optional trailing identifier rest is provided, it is
bound to the list of unused arguments not bound to any var.
Note R7RS does not have a disjoint keyword type or auto-quoting
syntax for keywords - they are simply identifiers. Thus when
passing keyword arguments they must be quoted (or otherwise
dynamically evaluated).
Example:
(define (make-person . o)
(let-keywords o ((name "John Doe")
(age 0)
(occupation job: 'unemployed))
(vector name age occupation)))
(list (make-person)
(make-person 'name: "Methuselah" 'age: 969)
(make-person 'name: "Dr. Who" 'job: 'time-lord 'age: 1500))
=> (#("John Doe" 0 unemployed) #("Methuselah" 969 unemployed) #("Dr. Who" 1500 time-lord))(let-keywords '(b: 2 a: 1 other: 9)
((a 0) (b 0) (c 0) rest)
(list a b c rest))
=> (1 2 0 (other: 9))let* equivalent to let-keywords*. Any required
default values are evaluated in left-to-right order, with
all preceding vars in scope.
Example:
(let-keywords* '(b: 5)
((a 1) (b (* a 2)) (c (* b 3)))
(list a b c))
=> (1 5 15)