On 2012-10-14, Luca Antonelli <
luke...@gmail.com> wrote:
> Hi, I have a list of functions in Common Lisp, say (1+ 1-), and apply them to a list of arguments, say (2 5), to obtain (3 4).
>
> (mapcar #'funcall '(1+ 1-) '(2 5)) does the trick, but, if I try to substitute 1+ with a lambda expression, such as
>
> (mapcar #'funcall '((lambda (x) (1+ x)) 1-) '(2 5))
This is as small inconsistency in Common Lisp. A lambda expression serves as a
function name, allowing you to use it in the first position of the list:
(1+ 3) ;; straight named call
((lambda (x) (1+ x)) 3) ;; analogous
But, funcall and other applicators do not support this. Although they accept a
name (i.e. symbol) they don't accept a lambda expression:
(funcall '1+ 3) ;; works
(funcall '(lambda (x) (1+ x)) 3) ;; does not
The function operator, however takes both names and lambda expressions and
converts them function objects that can be called:
(funcall (function 1+) 3)
(funcall (function (lambda (x) (1+ x))) args ...) ;; analogous, again
Unfortunately, funcall is an operator, so if we have a name or lambda
expression in a variable fname, we would have to (eval `(function ,fname)).
Do we need to reach for eval? We do not, because, fortunately, there is a
function which can do this job, and that is the coerce function:
(funcall (coerce '1+ 'function) 3)
(funcall (coerce '(lambda (x) (1+ x)) 'function) 3)
coerce takes a value and a type, converting the value to the given type.
So if you have a list containing a mixture of function names and lambda
expressions, you can apply arguments to those functions like this:
(mapcar (lambda (fname &rest args)
(apply (coerce fname 'function) args))
'(1+ 1- (lambda (x) (+ 10 x)))
'(1 1 1))
Now for some philosophical notes. The funcall oprator could easily have this
coerce behavior built in, but it doesn't. That's probably for efficiency
reasons.
Note how I went out of my way to avoid eval, but actually that is irrational.
** This is because coercing a piece of data representing source code to a
** function IS a form of run-time evaluation!
That is to say, there is hardly anything better about (coerce x 'function) than
(eval `(function ,x)) when x holds a lambda expression. In both cases the lambda
syntax contained in x has to be parsed at run time and converted to a function
object.
So this is probably why the support for run-time lambdas as function names is
not so consistent: good Lisp hackers instinctively avoid this sort of run-time
evaluation, unless the problem really calls for it (which generally happens
when functions need to be produced from run-time inputs to the program).
We usually want to present a lambda expression to the Lisp system as program
code, rather than a datum.