Spec-Zone.ru › Elisp

Анонимные функции

Хотя функции обычно определяются с помощью defun и получают имена одновременно, иногда удобно использовать явное лямбда-выражение — анонимную функцию. Анонимные функции допустимы везде, где допустимы имена функций. Они часто присваиваются в качестве значений переменных или как аргументы функциям; например, вы можете передать её как аргумент function к mapcar, которая применяет эту функцию к каждому элементу списка (см. Функции отображения). См. пример describe-symbols для реального примера этого.

При определении лямбда-выражения, которое будет использоваться как анонимная функция, вы в принципе можете использовать любой метод для построения списка. Но обычно вы должны использовать макрос lambda, или специальную форму function, или синтаксис чтения #':

Макрос: lambda args [doc] [interactive] body…

Этот макрос возвращает анонимную функцию со списком аргументов args, строкой документации doc (если есть), спецификацией интерактивного режима interactive (если есть) и формами тела, заданными body.

При динамической связи этот макрос эффективно делает lambda формы самоцитируемыми: вычисление формы, у которой CAR является lambda, возвращает саму форму:

(lambda (x) (* x x))
     ⇒ (lambda (x) (* x x))

Обратите внимание, что при вычислении с лексической связью результатом является объект замыкания (см. Замыкания).

Форма lambda имеет ещё один эффект: она сообщает оценщику Emacs и байт-компилятору, что её аргумент является функцией, используя function как подпрограмму (см. ниже).

Специальная форма: function function-object

Эта специальная форма возвращает function-object без его вычисления. В этом она похожа на quote (см. Цитата). Но в отличие от quote, она также служит заметкой для оценщика Emacs и байт-компилятора о том, что function-object предназначен для использования как функция. Предполагая, что function-object является допустимым лямбда-выражением, это имеет два эффекта:

  • При компиляции кода в байткод, function-object компилируется в объект функции байткода (см. Компиляция в байткод).
  • При включении лексической связи function-object преобразуется в замыкание. См. Замыкания.

Если function-object является символом, и код скомпилирован в байткод, компилятор байткода выведет предупреждение, если эта функция не определена или может быть неизвестна во время выполнения.

Синтаксис чтения #' является сокращением для использования function. Следующие формы полностью эквивалентны:

(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))

В следующем примере мы определяем функцию change-property, которая принимает функцию в качестве своего третьего аргумента, за которой следует функция double-property, которая использует change-property путём передачи ей анонимной функции:

(defun change-property (symbol prop function)
  (let ((value (get symbol prop)))
    (put symbol prop (funcall function value))))
(defun double-property (symbol prop)
  (change-property symbol prop (lambda (x) (* 2 x))))

Обратите внимание, что мы не цитируем форму lambda.

Если вы скомпилируете вышеприведенный код, анонимная функция также будет скомпилирована. Этого не произойдёт, если, скажем, вы построили анонимную функцию, приведя её в цитату как список:

(defun double-property (symbol prop)
  (change-property symbol prop '(lambda (x) (* 2 x))))

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

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/Anonymous-Functions.html

Spec-Zone.ru

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