Когда вы используете "применить" и когда "funcall"?

Общий Lisp HyperSpec говорит в записи funcall, что

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

Так как они как-то эквивалентны, когда вы используете apply, а когда funcall?

Ответ 1

Вы должны использовать funcall, если у вас есть один или несколько отдельных аргументов и apply, если у вас есть свои аргументы в списке

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

или

(defun passargs (a b) (funcall #'myfun a b))

Ответ 2

apply полезен, когда список аргументов известен только во время выполнения, особенно когда аргументы динамически читаются в виде списка. Вы все еще можете использовать funcall здесь, но вам нужно распаковать отдельные аргументы из списка, что неудобно. Вы также можете использовать apply как funcall, передав отдельные аргументы. Единственное, что он требует, это то, что последним аргументом должен быть список:

> (funcall #'+ 1 2)
3
> (apply #'+ 1 2 ())
3

Ответ 3

Хорошо, я думаю, что хорошим правилом было бы: использование применяется, когда вы не можете использовать funcall: последний более ясный, но также менее общий, чем применяется, поскольку он не позволяет вам вызывать функцию, число которой аргументы известны только во время выполнения.

Конечно, это только хорошая практика, и вы можете систематически делать это уродливым способом (систематически применяя применение), но, как вы, вероятно, заметили, использование уродливого способа, когда доступен очень похожий, но более чистый способ, не очень распространен -. lisp -y

Пример функции, которая требуется применять вместо funcall: вы могли бы реализовать карту таким образом, чтобы (map #'+ '(1 2) '(2 3)) и (map #'+ '(1 2) '(2 3) '(3 4)) работали (что имеет место со стандартной функцией) без использования apply (или eval, который обманывает)?

EDIT: как было указано, было бы глупо писать: (funcall func (first list) (second list) (third list) etc.) вместо (apply func list).