Вызов функций
Определение функций — это только половина дела. Функции ничего не делают, пока вы их не вызовете, то есть не скажете им работать. Вызов функции также известен как вызов.
Наиболее распространённый способ вызова функции — это вычисление списка. Например, вычисление списка (concat "a" "b") вызывает функцию concat с аргументами "a" и "b". См. Вычисление для описания вычисления.
Когда вы записываете список как выражение в своей программе, вы указываете, какую функцию вызвать и сколько аргументов ей передать, в тексте программы. Обычно этого достаточно. Иногда вам нужно вычислить во время выполнения, какую функцию вызвать. Для этого используйте функцию funcall. Когда вам также нужно определить во время выполнения, сколько аргументов передать, используйте apply.
- Функция: funcall функция &rest аргументы
-
funcallвызывает функцию с аргументами и возвращает то, что возвращает функция.Поскольку
funcallявляется функцией, все её аргументы, включая функцию, вычисляются перед вызовомfuncall. Это означает, что вы можете использовать любое выражение для получения вызываемой функции. Это также означает, чтоfuncallне видит выражений, которые вы пишете для аргументов, а только их значения. Эти значения не вычисляются повторно при вызове функции; действиеfuncallподобно обычной процедуре вызова функции, после того как её аргументы были вычислены.Аргумент функция должен быть либо функцией Lisp, либо примитивной функцией. Специальные формы и макросы не допускаются, потому что они имеют смысл только при предоставлении невычисленных выражений аргументов.
funcallне может предоставить их, потому что, как мы видели выше, она их никогда не знает в первую очередь.Если вам нужно использовать
funcallдля вызова команды и заставить её вести себя так, как будто она вызывается интерактивно, используйтеfuncall-interactively(см. Интерактивный вызов).(setq f 'list) ⇒ list(funcall f 'x 'y 'z) ⇒ (x y z)(funcall f 'x 'y '(z)) ⇒ (x y (z))(funcall 'and t nil) error→ Invalid function: #<subr and>
Сравните эти примеры с примерами
apply.
- Функция: apply функция &rest аргументы
-
applyвызывает функцию с аргументами, точно так же, какfuncall, но с одним отличием: последний из аргументов является списком объектов, которые передаются функции как отдельные аргументы, а не как один список. Мы говорим, чтоapplyраспределяет этот список, так что каждый отдельный элемент становится аргументом.applyс одним аргументом является особым: первый элемент аргумента, который должен быть непустым списком, вызывается как функция с остальными элементами как отдельными аргументами. Передача двух или более аргументов будет быстрее.applyвозвращает результат вызова функции. Как и в случае сfuncall, функция должна быть либо функцией Lisp, либо примитивной функцией; специальные формы и макросы не имеют смысла вapply.(setq f 'list) ⇒ list(apply f 'x 'y 'z) error→ Wrong type argument: listp, z
(apply '+ 1 2 '(3 4)) ⇒ 10(apply '+ '(1 2 3 4)) ⇒ 10(apply 'append '((a b c) nil (x y z) nil)) ⇒ (a b c x y z)(apply '(+ 3 4)) ⇒ 7Для интересного примера использования
apply, см. Определение mapcar.
Иногда бывает полезно зафиксировать некоторые аргументы функции в определённых значениях и оставить остальные аргументы на тот момент, когда функция будет фактически вызвана. Действие фиксации некоторых аргументов функции называется частичным применением функции12. Результатом является новая функция, которая принимает оставшиеся аргументы и вызывает исходную функцию со всеми объединёнными аргументами.
Вот как выполнить частичное применение в Emacs Lisp:
- Функция: apply-partially func &rest args
-
Эта функция возвращает новую функцию, которая при вызове вызовет func со списком аргументов, составленным из args и дополнительных аргументов, указанных во время вызова. Если func принимает n аргументов, то вызов
apply-partiallyсm <= nаргументами создаст новую функцию сn - mаргументами13.Вот как мы могли бы определить встроенную функцию
1+, если бы она не существовала, используяapply-partiallyи+, другую встроенную функцию14:(defalias '1+ (apply-partially '+ 1) "Increment argument by one.")
(1+ 10) ⇒ 11
Для функций Lisp характерно принимать функции в качестве аргументов или находить их в структурах данных (особенно в переменных хуков и списках свойств) и вызывать их с помощью funcall или apply. Функции, принимающие аргументы функций, часто называются функционалами.
Иногда, когда вы вызываете функционал, полезно предоставить в качестве аргумента функцию без действия. Вот два разных типа функций без действия:
- Функция: identity аргумент
Эта функция возвращает аргумент и не имеет побочных эффектов.
- Функция: ignore &rest аргументы
Эта функция игнорирует любые аргументы и возвращает
nil.
- Функция: always &rest аргументы
Эта функция игнорирует любые аргументы и возвращает
t.
Некоторые функции являются видимыми пользователю командами, которые могут вызываться интерактивно (обычно с помощью последовательности клавиш). Можно вызвать такую команду точно так же, как если бы она была вызвана интерактивно, используя функцию call-interactively . См. Интерактивный вызов.
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Calling-Functions.html