Инструменты пользователя

Инструменты сайта


examination:flp:question19

Определение функции в различных диалектах Лиспа

Мы рассмотрели определение функций в Коммон Лиспе. Приведем теперь сравнение принципов определения функций и их типов в более старых Лисп-системах и в Коммой Лиспе.

В различных диалектах языка Лисп вместо DEFUN используются следующие имена и формы: DEFINE, DEFINEQ, DE, CSETQ и другие. По типам функции разделяются, например в Интерлиспе на обыкновенные (normal function) и специальные.

Аргументы обыкновенной функции вычисляются слева направо перед вычислением значения самой функции. Число аргументов постоянно и списано в определении функции. Лисповские формы (QUOTE, SETQ и другие) не вычисляют аргументы. В то же время число аргументов функции в различных вызовах может отличаться.

В следующих четырех основных типах функций обобщены способы обработки аргументов и их число:

ТИП ФУНКЦИИ ВЫЧИСЛЕНИЕ АРГУМЕНТОВ КОЛИЧЕСТВО АРГУМЕНТОВ
EXPR Да Постояннее
EXPR* или LEXPR Да Переменное
FEXPR Нет Постоянное
FEXPR* Нет Переменное


Знак «*» - это звездочка Клини, и, как в теории языков, она обозначает повторение. Названия типов и разбиение на них взяты из систем Интерлисп и Маклисп. С помощью лямбда-выражения определяются «обыкновенные» функции типа EXPR. Им соответствуют функции Коммон Лиспа, у которых все параметры обязательны.

Функции, у которых количество вычисляемых аргументов может быть заранее неопределено, в Маклиспе называются LEXPR и в Интерлиспе - EXPR*. EXPR*/LEXPR определяется так же, как функция EXPR, только формальные параметры задаются не списком, а одним параметром.

При вычислении значения вызова сначала вычисляются значения аргументов, из них формируется безымянный стек и число фактических параметров становится значением формального параметра. Значение любого фактического параметра можно получить при помощи специальной функции, которая возвращает значение п-го аргумента. Функция LIST действует как функция типа EXPR*/LEXPR. Число ее аргументов, значения которых предварительно вычисляются, может быть неограниченно.

В Коммон Лиспе функции типа EXPR*/LEXPR можно определять с помощью параметра типа &REST, который связывается с несвязанным остатком списка значений параметров, имеющего произвольную длину.

SYMBOL-FUNCTION выдает определение функции

Ранее был рассмотрен предикат BOUNDP, проверяющий наличие у символа значения. Соответственно предикат FBOUNDP проверяет, связано ли с символом определение функции:

_(fboundp 'list1) 
> Т 


Значение символа можно было получить при помощи функции SYMBOL-VALUE. Аналогично функция SYMBOL-FUNCTION дает определение функции, связанное с символом:

_(symbol-function 'list1) 
> (LAMBDA (X У) (CONS X (CONS Y NIL))) 


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

_(setq list1 'а) 
> А 
_(list1 list1 'b) 
> (А В) 


Позднее мы увидим, что символы могут дополнительно к значению и определению обладать в более общем виде и другими свойствами, определенными пользователями, т.е. обладать списком свойств. Определение функции и значение переменных являются лишь двумя различными свойствами переменных, которые программист при необходимости может при помощи списка свойств дополнить или изменить. В некоторых системах (например, Franz Lisp) определение функции может храниться как значение символа, а не располагаться в специально отведенном месте в памяти. В Коммон Лиспе последняя возможность отсутствует:

_(setq 'список 
(lambda (х у) (cons x (cons у nil)))) 
> (LAMBDA (X У) (CONS X (CONS Y NIL)))) 
_(список 'a 'b) ; не работает в Коммон Лиспе 
> Error: Undefined function СПЖОК 


Значение символа в таких системах интерпретируется как определение функции лишь тогда, когда с символом не связано определение функции. В некоторых системах функцию можно задавать произвольным вычислимым выражением. В таких случаях говорят, что функции - это «полноправные граждане» (first class citizen).

examination/flp/question19.txt · Последние изменения: 2014/01/15 12:17 (внешнее изменение)