There are two types of combiners in Kernel, operative and
applicative. Both types are encapsulated. All combiners are immutable.
Two applicatives are
eq? iff their underlying combiners are
eq?-ness of operatives is only
constrained by the general rules for
eq?, which leave
considerable leeway for variation between implementations. klisp only
eq? those operatives constructed by the same call to
a constructor (e.g.
$vau). Two combiners are
iff they are
The primitive type predicate for type operative.
operative?returns true iff all the objects in
objectsare of type operative.
The primitive type predicate for type applicative.
applicative?returns true iff all the objects in
objectsare of type applicative.
<formals>should be a formal parameter tree;
<eformal>should be either a symbol or
<formals>does not have the correct form for a formal parameter tree, or if
<eformal>is a symbol that also occurs in
<formals>, an error is signaled.
vauexpression evaluates to an operative; an operative created in this way is said to be compound. The environment in which the
vauexpression was evaluated is remembered as part of the compound operative, called the compound operative’s static environment.
<objects>are copied as by
copy-es-immutableand the copies are stored as part of the operative being constructed. This avoids problem if these structures are later mutated.
When the compound operative created by
$vauis later called with an object and an environment, here called respectively the operand tree and the dynamic environment, the following happens:
- A new, initially empty environment is created, with the static environment as its parent. This will be called the local environment.
- A stored copy of the formal parameter tree formals is matched in the local environment to the operand tree, locally binding the symbols of formals to the corresponding parts of the operand tree. eformal is matched to the dynamic environment; that is, if eformal is a symbol then that symbol is bound in the local environment to the dynamic environment.
- A stored copy of the expressions is evaluated sequentially from left to right, with the last (if any) evaluated as a tail context, or if the list of expressions is empty, the result is inert.
NOTE: Because compound operatives are not a distinct type in Kernel, they are covered by the encapsulation of type operative. In particular, an implementation of Kernel cannot provide a feature that supports extracting the static environment of any given compound operative, nor that supports determining whether or not a given operative is compound.
wrapapplicative returns an applicative whose underlying combiner is
unwrapapplicative returns the underlying combiner of
<formals>should be a formal parameter tree.
$lambdaoperative is defined by the following equivalence:($lambda formals . objects) == (wrap ($vau formals #ignore . objects))
applycombines the underlying combiner of
objectin a tail context with dynamic environment
environment(if the long form is used) or in an empty environment (if the short form is used).
The following equivalences hold:(apply applicative object environment) == (eval (cons (unwrap applicative) object) environment) (apply applicative object) == (apply applicative object (make-environment))
listsmust be a nonempty list of lists; if there are two or more, they must all have the same length. If
listsis empty, or if all of its elements are not lists of the same length, an error is signaled.
applicativeelement-wise to the elements of the lists in
lists(i.e., applies it to a list of the first elements of the
lists, to a list of the second elements of the
lists, etc.), using the dynamic environment from which
mapwas called, and returns a list of the results, in order. The applications may be performed in any order, as long as their results occur in the resultant list in the order of their arguments in the original
listsis a cyclic list, each argument list to which
applicativeis applied is structurally isomorphic to
lists. If any of the elements of
listsis a cyclic list, they all must be, or they wouldn’t all have the same length. Let
a1...anbe their acyclic prefix lengths, and
c1...cnbe their cycle lengths. The acyclic prefix length
aof the resultant list will be the maximum of the
ak, while the cycle length
cof the resultant list will be the least common multiple of the
ck. In the construction of the result, applicative is called exactly
a + ctimes.
bytevectorsshould be non-empty lists of the corresponding type and all elements should be of the same length.
These applicatives behave as
mapexcept that the list of elements passed to
applicativeare the n-th chars, objects, or uint8s of the strings, vectors or bytevectors passed as arguments.
SOURCE NOTE: These are taken from r7rs.