Наша простая тестовая функция, (lambda (a b c) (+ a b c)),
определяет три переменные аргументов, поэтому ее необходимо вызывать с тремя
аргументами: если вы попытаетесь вызвать ее только с двумя или четырьмя
аргументами, вы получите ошибку wrong-number-of-arguments
(см. Ошибки).
Часто удобно писать функцию, которая позволяет опускать определенные
аргументы. Например, функция substring
принимает три аргумента — строку, начальный индекс и конечный
индекс, — но третий аргумент по умолчанию равен length
строки, если вы его опускаете. Также удобно, когда определенные функции
могут принимать неограниченное количество аргументов, как функции list
и +.
Чтобы указать необязательные аргументы, которые могут быть пропущены при
вызове функции, просто включите ключевое слово &optional
перед необязательными аргументами. Чтобы указать список из нуля или более
дополнительных аргументов, включите ключевое слово &rest
перед одним последним аргументом.
Таким образом, полная синтаксическая структура списка аргументов выглядит так:
(required-vars… [&optional [optional-vars…]] [&rest rest-var])
Квадратные скобки указывают, что пункты &optional и
&rest, а также переменные, следующие за ними, являются
необязательными.
Вызов функции требует один фактический аргумент для каждой из
required-vars. Может быть фактические аргументы для нуля или
более optional-vars, и не может быть фактических аргументов
после этого, если только список лямбда не использует &rest.
В этом случае может быть любое количество дополнительных фактических аргументов.
Если фактические аргументы для необязательных и дополнительных переменных
опущены, они всегда по умолчанию равны nil. Нет способа
для функции отличить явный аргумент nil от пропущенного
аргумента. Однако тело функции свободно рассматривать nil как
сокращение для какого-либо другого значимого значения. Именно это делает
substring; nil в качестве третьего аргумента
для substring означает использование длины предоставленной
строки.
Примечание Common Lisp: Common Lisp позволяет функции указывать, какое значение по умолчанию использовать, когда необязательный аргумент опущен; Emacs Lisp всегда использует
nil. Emacs Lisp не поддерживает переменныеsupplied-p, которые сообщают, был ли аргумент передан явно.
Например, список аргументов, выглядящий так:
(a b &optional c d &rest e)
привязывает a и b к первым двум фактическим
аргументам, которые являются обязательными. Если предоставлено еще один или
два аргумента, c и d привязываются к ним
соответственно; любые аргументы после первых четырех собираются в список, и
e привязывается к этому списку. Таким образом, если есть только
два аргумента, c, d и e
равны nil; если два или три аргумента, d и
e равны nil; если четыре аргумента или меньше,
e равен nil. Обратите внимание, что ровно
пять аргументов с явным аргументом nil, предоставленным для
e, приведут к тому, что этот аргумент nil
будет передан в виде списка с одним элементом, (nil), как и
любое другое одиночное значение для e.
Невозможно иметь обязательные аргументы после необязательных — это не имело
бы смысла. Чтобы понять, почему это должно быть так, предположим, что c в примере был необязательным, а d — обязательным.
Предположим, дано три фактических аргумента; для какой переменной будет третий
аргумент? Он будет использован для c или для d?
Можно утверждать обе возможности. Точно так же не имеет смысла иметь какие-либо
дополнительные аргументы (обязательные или необязательные) после аргумента
&rest.
Вот несколько примеров списков аргументов и корректных вызовов:
(funcall (lambda (n) (1+ n)) ; Один обязательный: 1) ; требует ровно один аргумент. ⇒ 2 (funcall (lambda (n &optional n1) ; Один обязательный и один необязательный: (if n1 (+ n n1) (1+ n))) ; 1 или 2 аргумента. 1 2) ⇒ 3 (funcall (lambda (n &rest ns) ; Один обязательный и один rest: (+ n (apply '+ ns))) ; 1 или более аргументов. 1 2 3 4 5) ⇒ 15