I'm still slightly unclear about funcall
.
I sometimes make mistakes with it and would like to clear this up by knowing the actual evaluation rule used by Common Lisp.
Specifically, what is the exact evaluation rule in CL for the form in function position as shown below. (funcall
in the correct version, (function fn)
in the incorrect version, which does not conform to the evaluation requirement of CL, as demonstrated by the error attained).
Knowing precisely what CL does here should explain why the second example below is an error.
(defun mappend (fn the-list)
"Apply fn to each element of list and append the results."
(if (null the-list)
nil
(append (funcall fn (first the-list))
(mappend fn (rest the-list)))))
(defun mappend (fn the-list)
"Apply fn to each element of list and append the results."
(if (null the-list)
nil
(append ((function fn) (first the-list)) ; <- this is WRONG, but why?
(mappend fn (rest the-list)))))
The second (incorrect) definition gives the error *** - SYSTEM::%EXPAND-FORM: #'FN should be a lambda expression
. Why is that?
My thinking was function
would get the function object denoted by the symbol fn
(hence handling the separate function namespace in CL), which if we just drop into the first position of a form, should act as a function. What am I not understanding?
Update: part of the answer is contained in 1.7 of Chapter 1 of PAIP, from which the first (correct) function above is taken. But it also seems that to understand this properly one needs to completely grasp the evaluation rule, and to understand that, the only way is to write a lisp interpreter...?
I wonder if this could be useful. (That's a download link to "McCarthy's original lisp" linked from here).
Update 2: I've now found that the notion referred to above of just "dropping into the first position of a form" is precisely what you can do in scheme, thus:
;; Exercise 1.4 in SICP:
(define (a-plus-abs-b a b)
((if (> b 0) + -) a b)) ; <- operator can be compound expression (in scheme)
However in CL you cannot do that.