1

I am going through a lisp book and I am looking at mapcar, my question is why is that this is valid:

> (mapcar #'+ '(1 2) '(3 4))

but this one isn't:

(mapcar + '(1 2) '(3 4))

in other words, is there a reason it was decided in lisp that the first argument to mapcar cannot be the function itself, and has to be its name? what purpose does this serve?

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
maininformer
  • 967
  • 2
  • 17
  • 31

2 Answers2

6

is there a reason it was decided in lisp that the first argument to mapcar cannot be the function itself, and has to be its name? what purpose does this serve?

It's just that in something like Common Lisp, the identifier + has multiple different purposes. It is a variable, a function, plus various other things.

writing + means the variable. It is used by the read eval print loop. The value of + is the last form that was evaluated, the value of ++ is the previous value of +, and the value of +++ is the previous value of ++.

To tell Common Lisp that you want to use the function value of an identifier +, one has to write (function +) or shorter #'+.

Thus

(mapcar (function +) '(1 2) '(3 4))

or shorter

(mapcar #'+ '(1 2) '(3 4))

actually means call mapcar with the function + and the lists (1 2) and (3 4)

There are two other ways to use the function +.

(mapcar '+ '(1 2) '(3 4))

Above will have Lisp retrieve the global function value of the symbol +.

Fourth, we can also have the function object be a part of the source code.

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
  • Thank you, I suppose, I would have expected that for `mapcar` for instance, for lisp to know what the type of the first argument needs to be and to look for that object in its appropriate namespace automatically. Do you perhaps know about the tradeoffs of putting this responsibility on the caller? – maininformer Jan 04 '21 at 06:30
  • 1
    @ plumSemPy: Lisp has only one rule for argument evaluation for function calls: the value of the argument is computed. – Rainer Joswig Jan 04 '21 at 09:06
  • @plumSemPy ... and [`mapcar`](http://www.lispworks.com/documentation/HyperSpec/Body/f_mapc_.htm) is a function (not a macro, nor a special form). – Will Ness Jan 04 '21 at 11:37
5

#'+ is a function. Common Lisp is what's called a 'lisp 2', which means that it has two namespaces: during evaluation of a compound form, like (+ a b), the function position is looked up in the function namespace while the other positions are looked up in the value namespace. This means that, for instance (append list list) does not make a list whose two elements are the list function: it makes a list whose two elements are whatever list happens to be bound to as a value.

But sometimes you need to get the function value of a name in a value position: an example is in the first argument of mapcar. To do that there is a special operator, function: (mapcar (function +) x y) adds the elements of two lists. Like quote, function has a read macro, which is #'.

(To make this more fun, mapcar actually expects a function designator so you can use the nsme of a function: (mapcar '+ x y) will work, although it is a bit horrid.)