When a procedure is called, the actual argument expression are evaluated, and the resulting values becomes the actual argument list. This is then matched against the formal parameter list (in the procedure definition), and assuming they match, the procedure body is called.
An argument list has three parts:
If there are no keyword arguments, then it ambiguous where prefix arguments and and where postfix arguments start. This is normally not a problem: the called procedure can split them up however it wishes.
Note that all keyword arguments have to be grouped together: It is not allowed to have a keyword argument followed by a plain argument followed by a keyword argument.
The argument list is constructed by evaluating the each operand of the procedure-call in order:
The expression is evaluated, yielding a single value that becomes a prefix or postfix argument.
The expression is evaluated. The resulting value combined with the keyword becomes a keyword argument.
The expression is evaluated. The result must be a sequence - a list, vector, or primitive array. The values of the sequence are appended to the resulting argument list. Keyword arguments are not allowed.
The expression is evaluted. The result can be a sequence; a hash table (viewed as a collection of (keyword,value) pairs); or an explicit argument list object, which is a sequence of values or keyword arguments. The values and keyword arguments are appended to the resulting argument list, though subject to the restriction that keyword arguments must be adjacent in the resulting argument list.
Sometimes it is useful to create an argument list out of pieces, take argument lists apart, iterate over them, and generally treat an argument list as an actual first-class value.
Explicit argument list objects can take multiple forms. The simplest is a sequence: a list, vector, or primitive array. Each element of the list becomes a value in the resulting argument list.
(define v1 '(a b c)) (define v2 (int 10 11 12 13)) (list "X" @v1 "Y" @v2 "Z") ⇒ ("X" a b c "Y" 10 11 12 13 "Z")
Things get more complicated once keywords are involved.
An explicit argument list with keywords is only allowed
when using the
@: splicing form,
@ form. It can be either
a hash table (anything the implement
or the types
Design note: An argument list with keywords is straightforward in Common Lisp and some Scheme implementations (including order versions of Kawa): It’s just a list some of whose
carcells are keyword objects. The problem with this model is neither a human or the compiler can reliably tell when an argument is a keyword, since any variable might have been assigned a keyword. This limits performance and error checking.
A hash table (anything the implement
whose keys are strings or keyword objects is
interpreted as a sequence of keyword arguments,
using the hash-table keys and values.
List of arguments represented as an immutable vector. A keyword argument takes two elements in this vector: A keyword object, followed by the value.
(define v1 (argvector 1 2 k1: 10 k2: 11 98 99)) (v1 4) ⇒ 'k2 (v1 5) ⇒ 11
v1 is viewed as a vector it
is equivalent to
(vector 1 2 'k1: 10 'k2: 11 98 99).
(Note in this case the keywords need to be quoted, since
vector constructor does not take keyword arguments.)
argvector “knows” which arguments
are actually keyword arguments, and can be examined using the
(kawa arglist) library discussed below:
(arglist-key-count (argvector 1 x: 2 3)) ⇒ 1 (arglist-key-count (argvector 1 'x: 2 3)) ⇒ 0 (arglist-key-count (vector 1 'x: 2 3)) ⇒ 0
In this case:
(fun 'a @:v1)
is equivalent to:
(fun 'a 1 2 k1: 10 k2: 11 98 99)
argvector, but compatible with
If there are no keyword arguments, returns a plain list.
If there is at least one keyword argument creates a special
gnu.mapping.ArgListPair object that implements the
list properties but internally wraps a
(import (kawa arglist))
In the following, args is an
(or in general any object that implement
Also, args can be a generalized list, in which case it
behaves like an
argvector that has no keyword arguments.
Call proc once, in order, for each argument in args.
The proc is called with two arguments,
(arglist-key-ref args i)
(arglist-arg-ref args i) for each i from 0
(arglist-arg-count args) (exclusive).
I.e. the first argument is either
#!null or the keyword (as a string);
the second argument is the corresponding argument value.
(define (print-arguments args #!optional (out (current-output-port))) (arglist-walk args (lambda (key value) (if key (format out "key: ~a value: ~w~%" key value) (format out "value: ~w~%" value)))))
Return the number of keyword arguments.
Number of prefix arguments, which is the number of arguments before the first keyword argument.
Return the number of non-keyword arguments. (The count includes neither the keywords nor the corresponding values.)
Get the index’th argument value. The index counts keyword argument values, but not the keywords themselves.
(arglist-arg-ref (arglist 10 11 k1: -1 19) 2) ⇒ -1 (arglist-arg-ref (arglist 10 11 k1: -1 19) 3) ⇒ 19
The index counts arguments like
If this is a keyword argument, return the corresponding keyword
(as a string); otherwise, return
#!null (which counts are false).
(arglist-key-ref (argvector 10 11 k1: -1 k2: -2 19) 3) ⇒ "k2" (arglist-key-ref (argvector 10 11 k1: -1 k2: -2 19) 4) ⇒ #!null
Search for a keyword matching key (which must be an interned string).
If there is no such keyword, return -1.
Otherwise return the keyword’s index as as argument to
Search for a keyword matching key (which must be an interned string). If there is no such keyword, return the default. Otherwise return the corresponding keyword argument’s value.
Argrest must be a sequence (list, vector, or string) or a primitive Java array. (This is an extension over standard Scheme, which requires that args be a list.) Calls the proc (which must be a procedure), using as arguments the argi... values plus all the elements of argrest.
(proc arg1 ...), unless proc and
all the following arguments are compile-time constants.
(That is: They are either constant, or symbols that have a global
binding and no lexical binding.) In that case, proc
is applied to the arguments at compile-time, and the result replaces
constant-fold form. If the application raises an exception,
a compile-time error is reported.
(constant-fold vector 'a 'b 'c)
is equivalent to
(quote #(a b c)), assuming
has not been re-bound.