## Application and Arguments Lists

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.

### Arguments lists

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 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:

`expression`

  The `expression` is evaluated, yielding a single value that becomes a prefix or postfix argument.

`keyword` `expression`

  The `expression` is evaluated. The resulting value combined with the `keyword` becomes a keyword argument.

`@``expression`

  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.

`@:``expression`

  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.

### Explicit argument list objects

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, not the `@` form. It can be either a hash table (anything the implement `java.util.Map` or the types `arglist` or `argvector`.

> 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 `car` cells 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 `java.util.Map`) whose keys are strings or keyword objects is interpreted as a sequence of keyword arguments, using the hash-table keys and values.

Type: `argvector`

Constructor: `argvector` ``operand```*`

> 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

> When `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 the `vector` constructor 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)

Type: `arglist`

Constructor: `arglist` ``operand```*`

> Similar to `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.ArgListPair` object that implements the usual `list` properties but internally wraps a `argvector`.

### Argument list library

    (import (kawa arglist))

In the following, `args` is an `arglist` or `argvector` (or in general any object that implement `gnu.mapping.ArgList`). Also, `args` can be a generalized list, in which case it behaves like an `argvector` that has no keyword arguments.

Procedure: `arglist-walk` `args` `proc`

> Call `proc` once, in order, for each argument in `args`. The `proc` is called with two arguments, corresponding to `(arglist-key-ref `args` `i`)` and `(arglist-arg-ref `args` `i`)` for each `i` from 0 up to `(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)))))

Procedure: `arglist-key-count` `args`

> Return the number of keyword arguments.

Procedure: `arglist-key-start` `args`

> Number of prefix arguments, which is the number of arguments before the first keyword argument.

Procedure: `arglist-arg-count` `args`

> Return the number of non-keyword arguments. (The count includes neither the keywords nor the corresponding values.)

Procedure: `arglist-arg-ref` `args` `index`

> 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

Procedure: `arglist-key-ref` `args` `index`

> The `index` counts arguments like `arglist-arg-ref` does. 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

Procedure: `arglist-key-index` `args` `key`

> 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 `arglist-key-ref`.

Procedure: `arglist-key-value` `args` `key` `default`

> 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.

### Apply procedures

Procedure: `apply` `proc` `argi``*` `argrest`

> `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`.

> Equivalent to: `(``proc` `argi`* `@``argrest``)`.

Syntax: `constant-fold` `proc` `arg1` `...`

> Same as `(`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 the `constant-fold` form. 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 `vector` has not been re-bound.