Spec-Zone.ru › Elisp

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

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

Самый распространённый способ вызова функции — вычислить список. Например, вычисление списка (concat "a" "b") вызывает функцию concat с аргументами "a" и "b". Описание вычисления см. в разделе Вычисление.

Когда вы записываете список в виде выражения в программе, вы указываете в тексте программы, какую функцию вызвать и сколько аргументов ей передать. Обычно это именно то, что нужно. Иногда требуется во время выполнения определить, какую функцию вызвать. Для этого используйте функцию funcall. Если вам также нужно во время выполнения определить, сколько аргументов передать, используйте apply.

Функция: funcall function &rest arguments

funcall вызывает function с аргументами arguments и возвращает то, что возвращает function.

Поскольку funcall — это функция, все её аргументы, включая function, вычисляются до вызова funcall. Это означает, что для получения вызываемой функции можно использовать любое выражение. Это также означает, что funcall не видит выражений, которые вы записываете для arguments, а видит только их значения. Эти значения не вычисляются повторно при вызове function; операция funcall подобна обычной процедуре вызова функции, аргументы которой уже вычислены.

Аргумент function должен быть функцией 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 function &rest arguments

apply вызывает function с аргументами arguments, как и funcall, но с одним отличием: последний элемент arguments — это список объектов, которые передаются function в качестве отдельных аргументов, а не как один список. Говорят, что apply распределяет этот список, так что каждый отдельный элемент становится аргументом.

apply с одним аргументом имеет особое значение: первый элемент аргумента, который должен быть непустым списком, вызывается как функция с оставшимися элементами в качестве отдельных аргументов. Передача двух или более аргументов будет быстрее.

apply возвращает результат вызова function. Как и в случае с funcall, function должна быть функцией 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.

Иногда полезно зафиксировать некоторые аргументы функции, задав им определённые значения, а остальные оставить для передачи при фактическом вызове функции. Фиксация некоторых аргументов функции называется её частичным применением. В результате получается новая функция, которая принимает остальные аргументы и вызывает исходную функцию со всеми аргументами вместе.

В Emacs Lisp это лучше всего делать с помощью анонимной функции. Например, если у вас есть функция ‘my-function’, принимающая два аргумента, можно сделать примерно так:

(mapcar (lambda (x) (my-function 123 x)) ...)

Частичное применение также можно реализовать с помощью функции apply-partially. Однако этот способ будет медленнее, чем использование анонимной функции с lambda.

Функция: apply-partially func &rest args

Эта функция возвращает новую функцию, которая при вызове вызовет func со списком аргументов, составленным из args и дополнительных аргументов, указанных при вызове. Если func принимает n аргументов, то вызов apply-partially с m <= n аргументами создаст новую функцию с n - m аргументами.

Вот как можно было бы определить встроенную функцию 1+, если бы её не существовало, с помощью apply-partially и +, другой встроенной функции:

(defalias '1+ (apply-partially '+ 1)
  "Increment argument by one.")
(1+ 10)
     ⇒ 11

Функции Lisp часто принимают функции в качестве аргументов или находят их в структурах данных (особенно в переменных-хуках и списках свойств) и вызывают их с помощью funcall или apply. Функции, принимающие функции в качестве аргументов, часто называют функционалами.

При вызове функционала иногда полезно передать в качестве аргумента функцию, ничего не выполняющую. Вот три разновидности таких функций:

Функция: identity argument

Эта функция возвращает argument и не имеет побочных эффектов.

Функция: ignore &rest arguments

Эта функция игнорирует любые аргументы arguments и возвращает nil.

Функция: always &rest arguments

Эта функция игнорирует любые аргументы arguments и возвращает t.

Некоторые функции являются видимыми пользователю командами, которые можно вызывать интерактивно (обычно с помощью последовательности клавиш). Такую команду можно вызвать точно так же, как если бы она была вызвана интерактивно, используя функцию call-interactively. См. раздел Интерактивный вызов.

Copyright © 1990-1996, 1998-2026 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