When do you use "apply" and when "funcall"?
Asked Answered
B

4

25

The Common Lisp HyperSpec says in the funcall entry that

(funcall function arg1 arg2 ...) 
==  (apply function arg1 arg2 ... nil) 
==  (apply function (list arg1 arg2 ...))

Since they are somehow equivalent, when would you use apply, and when funcall?

Barren answered 5/10, 2010 at 9:30 Comment(0)
F
38

You should use funcall if you have one or more separate arguments and apply if you have your arguments in a list

(defun passargs (&rest args) (apply #'myfun args))

or

(defun passargs (a b) (funcall #'myfun a b))
Firetrap answered 5/10, 2010 at 9:45 Comment(0)
B
12

apply is useful when the argument list is known only at runtime, especially when the arguments are read dynamically as a list. You can still use funcall here but you have to unpack the individual arguments from the list, which is inconvenient. You can also use apply like funcall by passing in the individual arguments. The only thing it requires is that the last argument must be a list:

> (funcall #'+ 1 2)
3
> (apply #'+ 1 2 ())
3
Belicia answered 5/10, 2010 at 11:31 Comment(0)
M
2

Well I think a good rule of thumb would be: use apply when you can't use funcall: the latter is clearer but is also less general than apply in that it doesn't allow you to call a function whose number of arguments is only known at runtime.

Of course it is only good practice and you could systematically do this the ugly way (systematically using apply), but as you've probably noticed, using the ugly way when a very similar but cleaner way is available is not very common-lisp-y.

Example of function that needs apply instead of funcall: could you implement map in such a way that (map #'+ '(1 2) '(2 3)) and (map #'+ '(1 2) '(2 3) '(3 4)) both work (which is the case with the standard function) without using apply (or eval, which is cheating)?

EDIT: as has also been pointed out, it would be silly to write:(funcall func (first list) (second list) (third list) etc.) instead of (apply func list).

Mourner answered 5/10, 2010 at 9:55 Comment(0)
T
-2

Apply function is curring the result, like it returns a function that applies to next argument, to next argument. It is important subject on functional programming languages.

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

(funcall 'mapcar 'list '((1 2)(3 4)))
(((1 2)) ((3 4)))

(apply 'mapcar 'list '((1 2)(3 4)))
((1 3) (2 4))
Terpsichore answered 21/8, 2021 at 20:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.