0

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.

mwal
  • 2,803
  • 26
  • 34
  • 1
    [3.1.2.1.2.3 Function Forms](http://clhs.lisp.se/Body/03_ababc.htm) could be useful too: it specifies the evaluation model for functions forms. The function is retrieved from the lexical environment, without being evaluated (or is a literal lambda form). See also [functional_evaluation](http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_f.htm#functional_evaluation) in the glossary. – coredump Oct 10 '19 at 11:56
  • 1
    See also https://stackoverflow.com/q/54210225/124319 – coredump Oct 10 '19 at 12:07
  • http://www.nhplace.com/kent/Papers/Technical-Issues.html – coredump Oct 10 '19 at 12:25
  • To quote PAIP: "The first element is evaluated in a unique way, as a function. This means it can either be a symbol or a lambda expression." (p21). So, my `(function fn)` above gives a function object, which is neither. I wonder is the next sensible step to look at the source of a lisp implementation? The JMC thing I linked above seems an old lisp and it might be best in this case to look at something that was definitely ANSI CL. – mwal Oct 10 '19 at 14:13
  • I found Peter Norvig's scheme interpreter in python (easy find if search for it), and one in javascript I'm not sure what to make of, but none of these address the question I had here which is specifically how CL works in this case. So, haven't found an actual CL interpreter (evaluator) available for illustration/teaching purposes; maybe src of an ansi cl implementation is all that's available? I looked at the source of gnu clisp but didn't make progress (i believe i'm looking for a function something like 'eval'? - parse being barely necessary for a lisp). – mwal Oct 10 '19 at 15:53
  • So not sure right now if I'd just be better doing SICP first, seems a pity. – mwal Oct 10 '19 at 15:55
  • 1
    See https://github.com/sbcl/sbcl/blob/master/src/code/full-eval.lisp#L1064, the first element of the list is not evaluated, it is used as-is to find out which function to call. – coredump Oct 10 '19 at 16:02
  • 1
    superb :) That's the answer to the OP in my view. – mwal Oct 10 '19 at 16:41

0 Answers0