13.1 Что такое функция?

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

В большинстве языков программирования каждая функция имеет имя. Но в Lisp функция в строгом смысле не имеет имени: это объект, который может опционально быть связан с символом (например, car), служащим именем функции. См. Именование функции. Когда функция получила имя, мы обычно также называем этот символ «функцией» (например, мы говорим «функция car»). В данном руководстве различие между именем функции и самим объектом функции обычно неважно, но мы будем обращать на него внимание там, где это имеет значение.

Некоторые объекты, подобные функциям, называемые специальными формами и макросами, также принимают аргументы для выполнения вычислений. Однако, как объясняется ниже, они не считаются функциями в Emacs Lisp.

Вот важные термины для функций и объектов, подобных функциям:

лямбда-выражение

Функция (в строгом смысле, т. е. объект функции), которая написана на Lisp. Они описаны в следующем разделе. См. Лямбда-выражения.

примитив

Функция, которая может быть вызвана из Lisp, но фактически написана на C. Примитивы также называются встроенными функциями или subr. Примеры включают функции car и append. Кроме того, все специальные формы (см. ниже) также считаются примитивами.

Обычно функция реализована как примитив, потому что она является фундаментальной частью Lisp (например, car), или потому что она предоставляет низкоуровневый интерфейс к службам операционной системы, или потому что она должна работать быстро. В отличие от функций, определенных в Lisp, примитивы могут быть изменены или добавлены только путем изменения исходников на C и перекомпиляции Emacs. См. Написание примитивов Emacs.

специальная форма

Примитив, который похож на функцию, но не вычисляет все свои аргументы обычным способом. Он может вычислять только некоторые аргументы, или вычислять их в необычном порядке, или несколько раз. Примеры включают if, and и while. См. Специальные формы.

макрос

Конструкция, определенная в Lisp, которая отличается от функции тем, что преобразует выражение Lisp в другое выражение, которое должно быть вычислено вместо исходного. Макросы позволяют программистам Lisp делать то же, что могут делать специальные формы. См. Макросы.

команда

Объект, который может быть вызван через примитив command-execute, обычно из-за того, что пользователь вводит последовательность клавиш, привязанную к этой команде. См. Интерактивный вызов. Команда обычно является функцией; если функция написана на Lisp, она превращается в команду с помощью формы interactive в определении функции (см. Определение команд). Команды, являющиеся функциями, также могут вызываться из выражений Lisp, как и другие функции.

Клавиатурные макросы (строки и векторы) также являются командами, хотя они не являются функциями. См. Клавиатурные макросы. Мы говорим, что символ является командой, если его функциональная ячейка содержит команду (см. Компоненты символа); такая именованная команда может быть вызвана с помощью M-x.

замыкание

Объект функции, очень похожий на лямбда-выражение, за исключением того, что он также содержит окружение лексических связываний переменных. См. Замыкания.

байт-код функция

Функция, скомпилированная байт-компилятором. См. Тип функции-замыкания.

объект автозагрузки

Заполнитель для реальной функции. Если объект автозагрузки вызывается, Emacs загружает файл, содержащий определение реальной функции, а затем вызывает реальную функцию. См. Автозагрузка.

Вы можете использовать функцию functionp для проверки, является ли объект функцией:

Функция: functionp object

Эта функция возвращает t, если object является функцией любого вида, т. е. может быть передан в funcall. Обратите внимание, что functionp возвращает t для символов, являющихся именами функций, и возвращает nil для символов, являющихся макросами или специальными формами.

Если object не является функцией, эта функция обычно возвращает nil. Однако представление объектов функций сложно, и из соображений эффективности в редких случаях эта функция может возвращать t, даже если object не является функцией.

Также можно узнать, сколько аргументов ожидает произвольная функция:

Функция: func-arity function

Эта функция предоставляет информацию о списке аргументов указанной function. Возвращаемое значение — это ячейка cons вида (min . max), где min — минимальное количество аргументов, а max — либо максимальное количество аргументов, либо символ many для функций с аргументами &rest, либо символ unevalled, если function является специальной формой.

Обратите внимание, что эта функция может возвращать неточные результаты в некоторых ситуациях, например:

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

В отличие от functionp, следующие функции не рассматривают символ как определение функции.

Функция: subrp object

Эта функция возвращает t, если object является встроенной функцией (т. е. примитивом Lisp).

(subrp 'message)            ; message — это символ,
     ⇒ nil                 ;   не объект subr.
(subrp (symbol-function 'message))
     ⇒ t
Функция: byte-code-function-p object

Эта функция возвращает t, если object является функцией байт-кода. Например:

(byte-code-function-p (symbol-function 'next-line))
     ⇒ t
Функция: compiled-function-p object

Эта функция возвращает t, если object является объектом функции, который представлен не в виде исходного кода ELisp, а в виде машинного кода или байт-кода. Более конкретно, она возвращает t, если функция встроенная (она же «примитив», см. Что такое функция?), или байт-скомпилирована (см. Байт-компиляция), или скомпилирована в нативный код (см. Компиляция Lisp в нативный код), или загружена из динамического модуля (см. Динамические модули Emacs).

Функция: interpreted-function-p object

Эта функция возвращает t, если object является интерпретируемой функцией.

Функция: closurep object

Эта функция возвращает t, если object является замыканием, что является частным видом объекта функции. В настоящее время замыкания используются для всех функций байт-кода и всех интерпретируемых функций.

Функция: subr-arity subr

Эта функция работает как func-arity, но только для встроенных функций и без косвенного обращения через символ. Она вызывает ошибку для не встроенных функций. Мы рекомендуем использовать func-arity вместо неё.

Функция: cl-functionp object

Эта функция подобна functionp, за исключением того, что она возвращает nil для списков и символов.

Функция: primitive-function-p object

Эта функция возвращает t, если object является встроенным примитивом, написанным на C (см. Тип примитивной функции). Обратите внимание, что специальные формы явно исключены, так как они не являются функциями. Используйте subr-primitive-p, если вам нужно распознавать также специальные формы.