Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

(newbie?) Question about map car and funcall

210 views
Skip to first unread message

Luca Antonelli

unread,
Oct 14, 2012, 9:38:10 AM10/14/12
to
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))

it raises an error: "FUNCALL: argument (LAMBDA (X) (1+ X)) is not a function."

(mapcar #'funcall '(#'(lambda (x) (1+ x)) 1-) '(2 5))
also doesn't work and returns "FUNCALL: #'(LAMBDA (X) (1+ X)) is not a function name; try using a symbol instead"

What's the difference between the lambda and 1+ ?

I've also noticed that if I use funcall without mapcar I have to use the function operator:
(funcall #'1+ 3) ==> 4
(funcall #'(lambda (x) (1+ x)) 3) ==> 4
all of them return no exceptions.

I think there is some relation with my problem, but I have no other clue. I tried some Internet research, but found no example similar to my case.

Luca

Marco Antoniotti

unread,
Oct 14, 2012, 9:55:30 AM10/14/12
to
LIST not QUOTE.

cl-prompt> (mapcar #'funcall (list '1+ '1+ (lambda (x) (+ x 42))) '(1 2 3))
(2 1 45)

--
MA

Petter Gustad

unread,
Oct 14, 2012, 9:55:35 AM10/14/12
to
Luca Antonelli <luke...@gmail.com> writes:

Consult the documentation on the macro quote (') which you use to
build the list:

'((lambda (x) (1+ x)) 1-) ->
((LAMBDA (X) (1+ X)) 1-)

vs:

(list #'(lambda (x) (1+ x)) #'1-) ->
(#<FUNCTION (LAMBDA #) {10053159EB}> #<FUNCTION 1->)

The following will work:

(mapcar #'funcall (list #'(lambda (x) (1+ x)) #'1-) '(2 5))

But you can also use ` and ,

(mapcar #'funcall `(,#'(lambda (x) (1+ x)) ,#'1-) '(2 5))


//Petter

--
.sig removed by request.

Nils M Holm

unread,
Oct 14, 2012, 10:11:31 AM10/14/12
to
Luca Antonelli <luke...@gmail.com> wrote:
> (mapcar #'funcall '((lambda (x) (1+ x)) 1-) '(2 5))
>
> it raises an error: "FUNCALL: argument (LAMBDA (X) (1+ X)) is not
> a function."

That's because (LAMBDA (X) (1+ X)) is a function, but
'(LAMBDA (X) (1+ X)) is a list.

You may try

(mapcar #'funcall `(,(lambda (x) (1+ x)) 1-) '(2 5))

instead. (Note: backquote instead of quote.)

--
Nils M Holm < n m h @ t 3 x . o r g > www.t3x.org

Luca Antonelli

unread,
Oct 14, 2012, 10:14:14 AM10/14/12
to
Thank you, it works (and, more important, I understood the error).

Luca

Il giorno domenica 14 ottobre 2012 15:55:36 UTC+2, Petter Gustad ha scritto:

Norbert_Paul

unread,
Oct 14, 2012, 10:21:50 AM10/14/12
to
Luca Antonelli 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))
>
> it raises an error: "FUNCALL: argument (LAMBDA (X) (1+ X)) is not a function."
That is true. The first element of '((lambda (x) (1+ x)) 1-) is simply the list (lambda (x) (1+ x)) and not
a function (just af if you had written (list 'lambda '(x) '(1+ x)) ).
Note that 'foo is a shorthand for writing (quote foo). Quote is not a function but a special operator thaat does not
evaluate its arguments.

> (mapcar #'funcall '(#'(lambda (x) (1+ x)) 1-) '(2 5))
> also doesn't work and returns "FUNCALL: #'(LAMBDA (X) (1+ X)) is not a function name; try using a symbol instead"
Here the first element of your list is the list (function (lambda (x) (1+ x))). Then notation "#'foo" is only a shorthand
for writing "(function foo)" (just like "'foo" is a shorthand for writing "(quote foo)").

> What's the difference between the lambda and 1+ ?
1+ is just a symbol that is fbound to a function. When you do "(apply some-symbol some-arguments)" then the
function definition of that symbol (in the "global" lexical environment) is used.
Neither the list (function (lambda (x) (1+ x))) nor (lambda (x) (1+ x)) are functions.
However, when either list is evaluated it /produces/ a function.

> I've also noticed that if I use funcall without mapcar I have to use the function operator:
> (funcall #'1+ 3) ==> 4
> (funcall #'(lambda (x) (1+ x)) 3) ==> 4
> all of them return no exceptions.
FUNCALL itself is a function that /evaluates/ all of its arguments, in particular #'(lambda (x) (1+ x)) which
then produces a function.
Try (mapcar #'funcall (list (lambda (x) (1+ x)) '1-) '(2 5))
or (mapcar #'funcall (list #'(lambda (x) (1+ x)) #'1-) '(2 5)) and variants.
The function LIST also evaluates the lambda form and produces a function object that can be applied.


Try also the followig on the REPL:

'(lambda (x) (1+ x)) ; Just a list that starts with LAMBDA.
'(lambada (x) (1+ x)) ; Just a list that starts not with LAMBDA.
'(salsa (x) (1+ x)) ; A variant of the above
'(merengue (x) (1+ x)) ; Ya variant of the above
'#'(lambda (x) (1+ x)) ; Just a list that starts with FUNCTION ...
(car '#'(lambda (x) (1 + x))) ; ... as you can see here.
'(function (lambda (x) (1+ x))) ; Just a List that starts with FUNCTION might be printed as "#'(LAMBDA (X) (1+ X))
(lambda (x) (1+ x)) ; The LAMBDA macro expands to #'(lambda (x) (1+ x))
(lambada (x) (1+ x)) ; Signals an error unless you have defined LAMBADA.
(function (lambda (x) (1+ x))) ; Evaluation of #'(lambda (x)...) on the REPL
#'(lambda (x) (1+ x)) ; Same as the above
(defmacro LAMBADA (args &rest body) ; you may also use SALSA or MERENGUE
(list 'FUNCTION (list* 'LAMBDA args body)))
(lambada (x) (1+ x)) ; No more error (unless you used SALSA or MERENGUE.

This should give you a feeling of the differences.

Norbert

Kaz Kylheku

unread,
Oct 14, 2012, 12:42:22 PM10/14/12
to
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.

Kaz Kylheku

unread,
Oct 14, 2012, 12:54:36 PM10/14/12
to
That's actually false. Funcall has to work somewhat like this.
(Imagine that system::builtin-apply is a built-in function applicator
which only understands function objects.)

(defun funcall (fspec &rest args)
(typecase (fspec)
;; fspec is a function object: just apply args to it
(function (system::builtin-apply fspec args))
;; fspec is a symbol: try to retrieve the associated function and apply
(symbol (system::builtin-apply (symbol-function func-or-name) args))))

Adding another case doesn't really hurt anything, since funcall already
has to check whether the input is a symbol or function.

(defun funcall (fspec &rest args)
(typecase (fspec)
;; fspec is a function object: just apply args to it
(function (system::builtin-apply fspec args))
;; fspec is a symbol: try to retrieve the associated function and apply
(symbol (system::builtin-apply (symbol-function func-or-name) args))
;; fspec might be a nonempty list, possibly a lambda form
(cons (system::builtin-apply (coerce fspec 'function) args))))

I would argue for that to be supported in a new revision of Common Lisp.

Then of course, everyone in this thread will have to reverse his silly
position.

"No wait, (lambda ...) IS a function, after all, quoted or not!"

Christophe Rhodes

unread,
Oct 14, 2012, 5:00:56 PM10/14/12
to
Kaz Kylheku <k...@kylheku.com> writes:

> Adding another case doesn't really hurt anything, since funcall already
> has to check whether the input is a symbol or function.
>
> (defun funcall (fspec &rest args)
> (typecase (fspec)
> ;; fspec is a function object: just apply args to it
> (function (system::builtin-apply fspec args))
> ;; fspec is a symbol: try to retrieve the associated function and apply
> (symbol (system::builtin-apply (symbol-function func-or-name) args))
> ;; fspec might be a nonempty list, possibly a lambda form
> (cons (system::builtin-apply (coerce fspec 'function) args))))
>
> I would argue for that to be supported in a new revision of Common Lisp.

With what semantics for the lookup of variables in the function not
present in the lambda list?

(By strict analogy with the function position, you might want lexical
lookup; however, that strategy would impose a very high cost on
implementations, requiring a reified lexical environment present at
runtime.)

Christophe

Kaz Kylheku

unread,
Oct 14, 2012, 7:42:36 PM10/14/12
to
On 2012-10-14, Christophe Rhodes <cs...@cantab.net> wrote:
> Kaz Kylheku <k...@kylheku.com> writes:
>
>> Adding another case doesn't really hurt anything, since funcall already
>> has to check whether the input is a symbol or function.
>>
>> (defun funcall (fspec &rest args)
>> (typecase (fspec)
>> ;; fspec is a function object: just apply args to it
>> (function (system::builtin-apply fspec args))
>> ;; fspec is a symbol: try to retrieve the associated function and apply
>> (symbol (system::builtin-apply (symbol-function func-or-name) args))
>> ;; fspec might be a nonempty list, possibly a lambda form
>> (cons (system::builtin-apply (coerce fspec 'function) args))))
>>
>> I would argue for that to be supported in a new revision of Common Lisp.
>
> With what semantics for the lookup of variables in the function not
> present in the lambda list?

From a lambda expression that is just a datum? No way.

> (By strict analogy with the function position, you might want lexical
> lookup; however, that strategy would impose a very high cost on
> implementations, requiring a reified lexical environment present at
> runtime.)

Worse than that, it means that (funcall x a b c) allows the list-datum stored
in x to make lexical references, which seems like nonsense. (Unless perhaps
your surname is Majorinc.)

funcall is a function which knows nothing about the caller's lexical
environment. If it did, it would be problematic. If someone wraps funcall, the
wrapper doesn't behave like funcall. (Unless we introduce an &environment
parameter to functions.)

Anyway, a closure should capture in the environment where it is made.
Arguably, the closure in this case is made inside funcall, not inside the
caller, where it is still just a piece of source code. So should it not capture
funcall's internal variables? :)

Barry Margolin

unread,
Oct 14, 2012, 10:17:15 PM10/14/12
to
In article <20121014...@kylheku.com>,
Kaz Kylheku <k...@kylheku.com> wrote:

> Adding another case doesn't really hurt anything, since funcall already
> has to check whether the input is a symbol or function.
>
> (defun funcall (fspec &rest args)
> (typecase (fspec)
> ;; fspec is a function object: just apply args to it
> (function (system::builtin-apply fspec args))
> ;; fspec is a symbol: try to retrieve the associated function and apply
> (symbol (system::builtin-apply (symbol-function func-or-name) args))
> ;; fspec might be a nonempty list, possibly a lambda form
> (cons (system::builtin-apply (coerce fspec 'function) args))))
>
> I would argue for that to be supported in a new revision of Common Lisp.

CLtL1 allowed this, but it was intentionally removed in ANSI Common
Lisp. Why would we put it back?

Allowing FUNCALL and APPLY to take a symbol is useful: you can put the
name of a function in a data structure, and if you redefine the function
it will use the updated definition.

What do you gain by being able to FUNCALL/APPLY a lambda expression,
that you can't do just as well by passing the function that you get by
actually evaluating the lambda expression?

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Kaz Kylheku

unread,
Oct 15, 2012, 2:36:31 AM10/15/12
to
On 2012-10-15, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article <20121014...@kylheku.com>,
> Kaz Kylheku <k...@kylheku.com> wrote:
>
>> Adding another case doesn't really hurt anything, since funcall already
>> has to check whether the input is a symbol or function.
>>
>> (defun funcall (fspec &rest args)
>> (typecase (fspec)
>> ;; fspec is a function object: just apply args to it
>> (function (system::builtin-apply fspec args))
>> ;; fspec is a symbol: try to retrieve the associated function and apply
>> (symbol (system::builtin-apply (symbol-function func-or-name) args))
>> ;; fspec might be a nonempty list, possibly a lambda form
>> (cons (system::builtin-apply (coerce fspec 'function) args))))
>>
>> I would argue for that to be supported in a new revision of Common Lisp.
>
> CLtL1 allowed this, but it was intentionally removed in ANSI Common
> Lisp. Why would we put it back?

To create a retro feeling, like wearing bell-bottom jeans.

> Allowing FUNCALL and APPLY to take a symbol is useful: you can put the
> name of a function in a data structure, and if you redefine the function
> it will use the updated definition.

> What do you gain by being able to FUNCALL/APPLY a lambda expression,
> that you can't do just as well by passing the function that you get by
> actually evaluating the lambda expression?

Optimization. If the function is never called, we didn't waste any time
processing the lambda expression.

We also gain pessimization. If the function is called more than once, we can
waste time parsing the lambda more than once, and then we can gloat about how
we don't care because it's the programmer time that is more valuable.

But mostly we gain increased newsgroup silence. Less of "gee, why doesn't this
just work".

Barry Margolin

unread,
Oct 15, 2012, 10:38:07 AM10/15/12
to
In article <201210142...@kylheku.com>,
The processing all takes place at compile time, so it shouldn't be
significant.

>
> But mostly we gain increased newsgroup silence. Less of "gee, why doesn't
> this
> just work".

I knew there was something we were leaving out of our design criteria in
X3J13. :)

Pascal J. Bourguignon

unread,
Oct 19, 2012, 8:24:45 AM10/19/12
to
Nils M Holm <news...@t3x.org> wrote:
> Luca Antonelli <luke...@gmail.com> wrote:
>> (mapcar #'funcall '((lambda (x) (1+ x)) 1-) '(2 5))
>>
>> it raises an error: "FUNCALL: argument (LAMBDA (X) (1+ X)) is not
>> a function."
>
> That's because (LAMBDA (X) (1+ X)) is a function, but
> '(LAMBDA (X) (1+ X)) is a list.

Let me argue that this formulation is the cause of this newbies problem.


(LAMBDA (X) (1+ X)) is NOT a function, but a list. (that is what funcall is
saying above!)
'(LAMBDA (X) (1+ X)) is indeed a list, of two elements: cl:quote and
(LAMBDA (X) (1+ X)).

WHEN Evaluated,
(LAMBDA (X) (1+ X)) RETURNS a function, and
'(LAMBDA (X) (1+ X)) RETURNS a list.

And that is the whole point of the OP question: quote prevented the
evaluation of its argument containing the lambda expression, therefore it
was left as a list, not evaluated to a function, hence the funcall
complain.


> You may try
>
> (mapcar #'funcall `(,(lambda (x) (1+ x)) 1-) '(2 5))
>
> instead. (Note: backquote instead of quote.)



--
__Pascal J. Bourguignon__

Nils M Holm

unread,
Oct 19, 2012, 11:08:19 AM10/19/12
to
Pascal J. Bourguignon <p...@informatimago.com> wrote:
> Nils M Holm <news...@t3x.org> wrote:
> > That's because (LAMBDA (X) (1+ X)) is a function, but
> > '(LAMBDA (X) (1+ X)) is a list.
>
> Let me argue that this formulation is the cause of this newbies problem.
>
> (LAMBDA (X) (1+ X)) is NOT a function, but a list. (that is what funcall is
> saying above!)
> '(LAMBDA (X) (1+ X)) is indeed a list, of two elements: cl:quote and
> (LAMBDA (X) (1+ X)).
>
> WHEN Evaluated,
> (LAMBDA (X) (1+ X)) RETURNS a function, and
> '(LAMBDA (X) (1+ X)) RETURNS a list.

Good point! I should have written

That's because (LAMBDA (X) (1+ X)) evaluates to a function, but
'(LAMBDA (X) (1+ X)) evaluates to a list.
0 new messages