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

mapcar on function arguments

21 views
Skip to first unread message

Dirk Bernhardt

unread,
Apr 25, 1997, 3:00:00 AM4/25/97
to

Hi,

I'm just learning Lisp. I have a problem to understand why in case of

(defun foo (f)
(funcall f 3 4))
(foo #'+)
==> 7
(foo #'*)
==> 12

mapcar, which is supposed to apply its first argument to each element of
its second argument (according to my documentation), will not evaluate

(mapcar #'foo '(#'+ #'*))

, but the evaluation of

(mapcar #'foo '(+ *))
==> (7 12)

works instead. Can you help me?

Ciao,
- Krid -
--
ungeduscht, geduzt und ausgebuht

Lyman S. Taylor

unread,
Apr 25, 1997, 3:00:00 AM4/25/97
to

In article <87iv1ag...@comnets.rwth-aachen.de>,
Dirk Bernhardt <kr...@comnets.rwth-aachen.de > wrote:
>Hi,


>(mapcar #'foo '(#'+ #'*))

^^^^^^^^^^
|||||||||| the above evaluates in the Listener to????

CL-USER 11 > '( #'+ #'*)
((FUNCTION +) (FUNCTION *))

the identity of function ?? below is left
as an exercise for the reader. :-)
[ Hint: you want to create a list, right?]

CL-USER 14 > (?? #'+ #'* )
(#<Function +> #<Function *>)

Note the following...

CL-USER 15 > (mapcar #'functionp '(#'+ #'*))
(NIL NIL)

CL-USER 16 > (mapcar #'functionp (?? #'+ #'* ))
(T T)

CL-USER 17 > (mapcar #'listp '( #'+ #'* ))
(T T)

CL-USER 18 > (mapcar #'listp (?? #'+ #'* ))
(NIL NIL)

>(mapcar #'foo '(+ *))

For better or worse, you may also pass a symbol, as opposed to a function,
as the first argument of mapcar. In this case mapcar will retrieve the
function bound to the GLOBAL symbol ( therefore it is a better practice
to be specific and send a function rather than symbol... least at some
point in the future get entangled with lexical scoping issues ).


--

Lyman S. Taylor "Because no matter where you go,
(ly...@cc.gatech.edu) there you are."
Buckaroo Banzai

Kent M Pitman

unread,
Apr 25, 1997, 3:00:00 AM4/25/97
to

> (defun foo (f) (funcall f 3 4))

> mapcar, which is supposed to apply its first argument to each element of
> its second argument (according to my documentation), will not evaluate

> (mapcar #'foo '(#'+ #'*))

Try: (mapcar #'foo (list #'+ #'*))

#'+ and #'* are not themselves functions, they evaluate to functions.
But you have quoted the list in which they are held, so they don't get evaluated.
Since #'+ is just the same as (function +) and since that list is not a function,
you probably get some sort of error.

> , but the evaluation of
>

> (mapcar #'foo '(+ *))

> ==> (7 12)

works instead. Can you help me?

The reason this works is because although + and * are not functions, they are
symbols, and symbols are allowed to be used in functional positions. The function
chosen in that case will be (symbol-function '+) or (symbol-function '*).

In production code, if this were really a constant list,
one would would probably do:

(defun bar ()
(mapcar #'foo (load-time-value (list #'+ #'*))))

to avoid runtime consing on each call to bar. This would cause the list to
be computed once at load-time and then re-used as a constant on each call to bar.
On the other hand, if you plan to redefine the functions in the list (well,
it's not a good idea to redefine + and *, but if they were f and g, for example)
then these two differ slightly in semantics:

(defun baz-1 ()
(mapcar #'foo (load-time-value (list #'f #'g))))

(defun baz-2 ()
(mapcar #'foo '(f g)))

The things to note are that
- baz-1 must have f and g defined BEFORE it is loaded.
- baz-2 may use forward references to f and g, provided f and g
are defined by the time baz-2 is first called
- baz-2 will notice redefinitions of f and g, while baz-1
won't notice redefinitions of f and g after the first call to
baz-1 [i'd have to check the spec closely to know whether or
not it's defined what happens if f and g are redefined between
load-time of baz-1 and first call to baz-1.]

A lot of people don't know about load-time-value and tend to use

(defvar *baz-1a-fns* (list #'f #'g))
(defun baz-1a () (mapcar #'foo *baz-1a-fns*))

but that involves the introduction of an extra variable that really you
don't need, and is technically not optimizable by a really good compiler
in as good a way as the load-time-value operation is.

This is probably more information than you wanted as a beginner. But
perhaps it will give you some things to look up and to learn from.

You can get online documentation on any operator mentioned here from
the Common Lisp HyperSpec(TM) at
http://www.harlequin.com/books/HyperSpec/

Good luck and happy learning.
--Kent Pitman
k...@harlequin.com


Ken Tilton

unread,
Apr 26, 1997, 3:00:00 AM4/26/97
to

Dirk Bernhardt wrote:
>
> Hi,
>
> I'm just learning Lisp. I have a problem to understand why in case of
>
> (defun foo (f)
> (funcall f 3 4))
> (foo #'+)
> ==> 7
> (foo #'*)
> ==> 12
>
> mapcar, which is supposed to apply its first argument to each element of
> its second argument (according to my documentation), will not evaluate
>
> (mapcar #'foo '(#'+ #'*))
>
> , but the evaluation of
>
> (mapcar #'foo '(+ *))
> ==> (7 12)
>
> works instead. Can you help me?
>

Not to be pedantic, but in the spirit of "give me a fish I eat today,
teach me to fish I eat for the rest of my life"...

I suggest you modify #'foo to print its argument and the argument's
type, or even inspect its argument. Hint: (list <something>) is not
always the same as '(<something>).

Cheers,

Ken

Erik Naggum

unread,
Apr 26, 1997, 3:00:00 AM4/26/97
to

* Dirk Bernhardt

| mapcar, which is supposed to apply its first argument to each element of
| its second argument (according to my documentation), will not evaluate
| (mapcar #'foo '(#'+ #'*)), but the evaluation of

| (mapcar #'foo '(+ *)) ==> (7 12)
| works instead. Can you help me?

* Ken Tilton


| I suggest you modify #'foo to print its argument and the argument's type,
| or even inspect its argument. Hint: (list <something>) is not always the
| same as '(<something>).

I'll take that hint a bit further, since this is a frequent problem for
beginners in Lisp (as witnessed mostly in Emacs Lisp):

the value of '(x y z) is identical to the value of (list 'x 'y 'z) in all
but one respect (the time at which the list is constructed).

'x is identical to (quote x) in all respects.

#'x is identical to (function x) in all respects.

you should get the idea, now.

#\Erik
--
if we work harder, will obsolescence be farther ahead or closer?

0 new messages