When would I use mapc instead of mapcar?
Asked Answered
S

2

6

So far I have been using mapcar to apply a function to all elements of a list, such as:

(mapcar (lambda (x) (* x x))
        '(1 2 3 4 5))
;; => '(1 4 9 16 25)

Now I learned that there is also the mapc function which does exactly the same, but does not return a new list, but the original one:

(mapc (lambda (x) (* x x))
      '(1 2 3 4 5))
;; => '(1 2 3 4 5)

What's the intent of this function? When would I use mapc instead of mapcar if I am not able to access the result?

Simla answered 31/5, 2014 at 9:46 Comment(0)
M
16

The Common Lisp Hyperspec says:

mapc is like mapcar except that the results of applying function are not accumulated. The list argument is returned.

So it is used when mapping is done for possible side-effects. mapcar could be used, but mapc reduces unnecessary consing. Also its return value is the original list, which could be used as input to another function.

Example:

(mapc #'delete-file (mapc #'compile-file '("foo.lisp" "bar.lisp")))

Above would first compile the source files and then delete the source files. Thus the compiled files would remain.

(mapc #'delete-file (mapcar #'compile-file '("foo.lisp" "bar.lisp")))

Above would first compile the source files and then delete the compiled files.

Mob answered 31/5, 2014 at 11:34 Comment(0)
P
3

You should use mapc when you don't need to use the result of applying the function over the list. For example, to print out every element, you could use:

(mapc #'print '(1 2 3 4 5))

Technically, the print function will return something, but you don't need to use it, so you ignore it.

Poddy answered 31/5, 2014 at 9:57 Comment(3)
Ah, okay :-)). But it wouldn't be wrong if I used mapcar here as well, would it?Simla
The only time I can think of where it would make a difference is if it were the last statement in a function or a progn, as the result from that would be returned. But otherwise, yeah, it wouldn't be wrong.Poddy
@GoloRoden The code won't do the wrong thing if you used mapcar, but people who look at your code will scratch their head and wonder why you didn't use mapc instead, if the return value is not used. (In Scheme, the situation is a little different: for-each (Scheme analogue to mapc) calls your function on list elements left-to-right, whereas map (Scheme analogue to mapcar) does not specify an order (many implementations actually use right-to-left), so you should only use map for pure functions.)Nevus

© 2022 - 2024 — McMap. All rights reserved.