Common Lisp HyperSpec 在funcall
条目中说
(funcall function arg1 arg2 ...)
== (apply function arg1 arg2 ... nil)
== (apply function (list arg1 arg2 ...))
由于它们在某种程度上是等效的,您何时会使用apply
,何时使用funcall
?
答案 0 :(得分:21)
如果您有一个或多个单独的参数,则应使用funcall
;如果列表中包含参数,则应使用apply
(defun passargs (&rest args) (apply #'myfun args))
或
(defun passargs (a b) (funcall #'myfun a b))
答案 1 :(得分:6)
apply
非常有用,尤其是当参数作为列表动态读取时。你仍然可以在这里使用funcall
,但是你必须从列表中解包各个参数,这是不方便的。您也可以通过传递单个参数来使用apply
之类的funcall
。它唯一需要的是最后一个参数必须是一个列表:
> (funcall #'+ 1 2)
3
> (apply #'+ 1 2 ())
3
答案 2 :(得分:1)
嗯,我认为一个好的经验法则是:当你不能使用funcall时使用apply:后者更清晰,但也不如应用,因为它不允许你调用一个数量为参数只在运行时才知道。
当然这只是一种很好的做法,你可以系统地以丑陋的方式(系统地使用应用)这样做,但正如你可能已经注意到的那样,当一个非常相似但更干净的时候使用丑陋的方式方式可用并不常见 - lisp-y。
需要应用而不是funcall的函数示例:
您是否可以使用(map #'+ '(1 2) '(2 3))
和(map #'+ '(1 2) '(2 3) '(3 4))
两种方式实现地图(标准函数就是这种情况)而不使用apply(或eval,这是作弊)?
编辑:正如我们已经指出的那样,写(funcall func (first list) (second list) (third list) etc.)
而不是(apply func list)
是愚蠢的。