Search code examples
common-lisplisp-2

Why must I funcall a function returned from another?


Why doesn't this work?

( ((lambda () (lambda (x) (funcall #'1+ x)))) 2)
 ; yields Compile-time error: illegal function call

I ran into a situation like this and it later turned out that a funcall fixes it, i.e.

(funcall ((lambda () (lambda (x) (funcall #'1+ x)))) 2) ; => 3

I'm confused because it seems like the first one should work, because I actually have a function I'm calling, not just a symbol that may belong to either namespace (i.e. (type-of ((lambda () #'1+))) ; => FUNCTION). I thought it would be kind of like how you don't need to funcall a lambda for example, e.g.((lambda (x) x) :HI) ; => :HI. What am I missing?


Solution

  • The syntax of Common Lisp requires that, everytime you want to call a function through a compund form of the type:

    (f a1 a2 ... an)
    

    the first element of the list, f, must be a symbol denoting a function name, or a list denoting a lambda expression, i.e. (see the manual):

    lambda expression n. a list which can be used in place of a function name in certain contexts to denote a function by directly describing its behavior rather than indirectly by referring to the name of an established function; its name derives from the fact that its first element is the symbol lambda.

    So, this basically means that you cannot have as first element any expression that returns a function as value. In those cases, you must use funcall.

    So, in your second example, the first argument of the funcall is ((lambda () (lambda (x) (funcall #'1+ x)))), which is a correct coumpound form, in which the first element of the list is the lambda expression (lambda () (lambda (x) (funcall #'1+ x))) (applied to an empty list of arguments).

    In the first example, instead, you have as first element of the list an expression returning a function, so that you must use funcall.