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?
The syntax of Common Lisp requires that, everytime you want to call a function through a compund form of the type:
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):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
.This works: First your identical definitions:
However, invoke using funcall:
Common Lisp uses the word form for everything which can be evaluated. A form is either
foo
A compound form is either
(<special-operator> ...)
(lambda (...) ...)
(<macroname> ...)
(<functionname> ...)
.Above is the set of compound forms. The ANSI Common Lisp specification provides no way to add a new type of forms or a different syntax. The interface of what forms the functions like
EVAL
orCOMPILE
accept is not extensible.So something like
is not valid Common Lisp. This is not meaningful in Common Lisp:
Note that Common Lisp allows lambda forms, special operators, macro names and function names as the first element in a compound form. But it does not allow variables and it does not allow other compound forms as the first element in a compound form.
Means this is not meaningful in Common Lisp:
Thus
((foo 1) 2)
or(((foo 1) 2) 3)
or((((foo 1) 2) 3) 4)
or(((((foo 1) 2) 3) 4) 5)
is not legal in Common Lisp. You get the idea. To call function objects returned from function calls, we have to use(funcall (foo ...) ...)
. This makes calling returned function objects more obvious than just((foo ...) ...)
.Let's praise the designers of Common Lisp for this feature. Otherwise I might have to look at possibly meaningful code beginning with
and it would be very hard to figure out what it does. Basically that would be write-only code.
Your question:
Why must I funcall a function returned from another?
The short answer: because the syntax does not allow other ways, in Common Lisp.
I have read this article and then modified my code below:
And call it in this way
((my-func 2) 3)
,but it also report "illegal function call". I think my code is keeping with lambda calculus,but where is wrong.In my opinion, (my-func 2) returns symbol *my_fun*, and the function cell of *my-fun* points to a function object, so ((my-func 2) 3) => (*my-fun* 3) => ((lambda (v1) (+ 2 v1)) 3) => (+ 2 3) => 5