Когда вы используете "применить" и когда "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)
.