Spec-Zone.ru › Elisp

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

Определение функций — это только половина дела. Функции ничего не делают, пока вы их не вызовете, то есть не скажете им работать. Вызов функции также известен как вызов.

Наиболее распространённый способ вызова функции — это вычисление списка. Например, вычисление списка (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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API