When the first element of a list form evaluates to a function object (either a primitive subroutine or a closure), all other elements in the list are evaluated sequentially from left-to-right, then these values are applied to the function definition. The result returned by the function is then taken as the value of the whole list form.
For example, consider the form
(/ 100 (1+ 4)). This is a
function call to the function stored in the variable
/ form is evaluated, it is a variable containing a data
value representing the primitive subroutine for integer division. Then
100 form is evaluated: it is a number, so self-evaluates to
100. Next the form
(1+ 4) is evaluated. This is
also a function call and computes to a value of
5 which becomes
the second argument to the
/ function. Now the
is applied to its evaluated arguments of
returns the value
20. This then becomes the value of the form
(/ 100 (1+ 4)).
(/ 100 (1+ 4)) ≡ (/ 100 5) ⇒ 20
Or another example,
(+ (- 10 (1- 7)) (* (1+ 2) 4) ≡ (+ (- 10 6) (* (1+ 2) 4) ≡ (+ 4 (* (1+ 2) 4) ≡ (+ 4 (* 3 4)) ≡ (+ 4 12) ⇒ 16
The system is also capable of eliminating tail calls where possible, allowing tail-recursive function definitions to run with bounded space requirements.
A tail-call is a function call that occurs immediately before exiting the containing function. Since the containing function need not receive the result of the function call, it is possible to, in effect, exit from the containing function before invoking the called function.
Note however, that this is only possible where none of the dynamic
features of the language (i.e. bindings to special variables,
are currently active in the containing function.
Consider, for example, the following function:
(defun print-list (l) (unless (null l) (format standard-output "%s\n" (car l)) (print-list (cdr l))))
the call to
print-list occurs in the tail-position of the
function. This means that the call may be made after removing the
previous call to
print-list from the interpreter’s stack of
[ XXX currently the interpreter is incapable of eliminating tail calls to subrs, i.e. Lisp functions implemented in C ]