7.3 Вызов функции

Наиболее примитивная форма вызова функции в Lisp’е, конечно, не имеет имени. Любой список, который не интерпретируется как макровызов или вызов оператора, рассматривается как вызов функции. Другие конструкции предназначены для менее распространённых, но тем не менее полезных ситуаций.

[Функция] apply function arg &rest more-args

Функция применяет функцию function к списку аргументов.

Все аргументы, кроме function передаются в применяемую функцию. Если последний аргумент список, то он присоединяется в конец к списку первых аргументов. Например:

(setq f ’+) (apply f ’(1 2))  3
(setq f #’-) (apply f ’(1 2))  -1
(apply #’max 3 5 ’(2 7 3))  7
(apply ’cons ’((+ 2 3) 4))
        ((+ 2 3) . 4) not (5 . 4)
(apply #’+ ’())  0

Следует отметить, что если функция принимает именованные аргументы, ключевые символы должны быть перечислены в списке аргументов так же, как и обычные значения:

(apply #’(lambda (&key a b) (list a b)) ’(:b 3))  (nil 3)

Это бывает очень полезным в связке с возможностью &allow-other-keys:

(defun foo (size &rest keys &key double &allow-other-keys)
  (let ((v (apply #’make-array size :allow-other-keys t keys)))
    (if double (concatenate (type-of v) v v) v)))

(foo 4 :initial-contents ’(a b c d) :double t)
    #(a b c d a b c d)


[Функция] funcall fn &rest arguments

(funcall fn a1 a2 ... an) применяет функцию fn к аргументам a1, a2, ..., an. fn не может быть оператором или макросом, это не имело бы смысла.

Например:

(cons 1 2)  (1 . 2)
(setq cons (symbol-function ’+))
(funcall cons 1 2)  3

Различие funcall и обычным вызовом функции в том, что функция получается с помощью обычных Lisp вычислений, а не с помощью специальной интерпретации первой позиции в списке формы.


[Константа] call-arguments-limit

Значение call-arguments-limit положительное целое, которое отображает невключительно максимальное количество аргументов, которые могут быть переданы в функцию. Эта граница зависит от реализации, но не может быть меньше 50. (Разработчикам предлагается сделать этот предел большим на сколько это возможно без ущерба для производительности.) Значение call-argument-limit должно, как минимум, равняться lambda-parameters-limit. Смотрите также multiple-values-limit.