When a procedure is called, the actual argument expressions 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:
Zero or more prefix arguments, each of which is a value. These typically get bound to named required or optional formal parameters, but can also get bound to patterns.
Zero or more keyword arguments, each of which is a keyword (an identifier specified with keyword syntax) combined with a value. These are bound to either named keyword formal parameters, or bundled in with a rest parameter.
Zero or more postfix arguments, each of which is a value. These are usually bound to a “rest” formal parameter, which receives any remaining arguments.
If there are no keyword arguments, then it ambiguous where prefix arguments end 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 each
procedure-call in order:
expression is evaluated, yielding a single value
that becomes a prefix or postfix argument.
expression is evaluated. The resulting value combined
keyword becomes a keyword argument.
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.
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, 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 implements
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
v1is 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 the
vectorconstructor does not take keyword arguments.) However, the
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
list. If there are no keyword arguments, returns a plain list. If there is at least one keyword argument creates a special
gnu.mapping.ArgListPairobject that implements the usual
listproperties but internally wraps a
(import (kawa arglist))
In the following,
args is an
(or in general any object that implement
args can be any sequence, in which case it
behaves like an
argvector that has no keyword arguments.
proconce, in order, for each argument in
procis called with two arguments, corresponding to
ifrom 0 up to
(arglist-arg-count(exclusive). I.e. the first argument is either
#!nullor 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 arguments. The count includes the number of keyword arguments, but not the actual keywords.(arglist-arg-count (arglist 10 11 k1: -1 19)) ⇒ 4
index’th argument value. The
indexcounts 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
indexcounts arguments like
arglist-arg-refdoes. If this is a keyword argument, return the corresponding keyword (as a string); otherwise, return
#!null(which counts as 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 an 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.
Argrestmust be a sequence (list, vector, or string) or a primitive Java array. (This is an extension over standard Scheme, which requires that
argsbe a list.) Calls the
proc(which must be a procedure), using as arguments the
argi... values plus all the elements of
procand 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,
procis applied to the arguments at compile-time, and the result replaces the
constant-foldform. If the application raises an exception, a compile-time error is reported. For example:(constant-fold vector 'a 'b 'c)
is equivalent to
(quote #(a b c)), assuming
vectorhas not been re-bound.