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

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


examination:flp:question23

Работа предикатов DEFUN и SYMBOL-FUNCTION в РС – Лиспе.

Функция DEFUN

Функция DEFUN добавлена исключительно для совместимости с более поздними версиями Лиспа. DEFUN позволяет создавать функции типа EXPR несколько проще, чем базовая функция SEXPR. Функция принимает три аргумента: имя вновь создаваемой функции (атом); список формальных параметров (список) и тело функции без атома LAMBDA (тоже список). При успехе DEFUN возвратит имя вновь созданной функции (первый аргумент). Создадим функцию, вычисляющую сумму элементов списка произвольной длины, состоящего из чисел или констант, имеющих числовое значение. Это будет рекурсивная функция, работающая следующим образом: если список пуст, функция должна вернуть нуль. Если аргумент функции - атом, то функция должна вернуть этот атом в качестве значения (предполагаем, что на вход функции подается список из чисел). Наконец, если аргумент - список, то функция берет значение головы списка и прибавляет к нему значение функции, взятой от хвоста списка (стандартное использование рекурсии). Все это выглядит так:

(defun Сумма (x)
             (cond ((null x) 0)
                   ((Atom x) x) 
                   (T (+ (car x) (Сумма (Cdr x))))
              )
)

Если вычислить (Сумма '(1 2 3 4)), получим результат 10 - функция работает.

Функция - (symbol-function symbol)

Функция symbol-function возвращает текущее глобальное определение функции, ассоциируемой с символом symbol. Если символ не содержит определения функции, Лисп генерирует сообщение об ошибке. Стоит иметь в виду, что определение может быть как функцией, так и объектом, представляющим специальную форму или макроопределение. Однако, в последнем случае попытка вызвать объект как функцию приведет к ошибке. Если при разработке программы, например, при написании интерпретатора, возникает необходимость единообразно обрабатывать макросы, специальные формы и функции, то целесообразно вначале проверить тип символа с помощью macro-function и special-form-p, а уже затем вызывать его функциональное значение, но только в том случае если оба перечисленных выше теста закончились неудачно (то есть вернули false).

Функция особенно полезна при реализации интерпретаторов языков, встроенных в Лисп-систему.

Функция symbol-function не обеспечивает доступа к значениям лексических имен функций, генерируемых с помощью

flet или labels; она может работать только с глобальными значениями (определениями) функций.

Эти глобальные определения могут быть изменены с помощью применения setf к результату symbol-function. Выполнение этой операции приводит к тому, что символу соответствует единственное глобальное определение функции; все предыдущие определения, независимо от того, были ли они макросами или функциями, теряются. При этом не допускается переопределение специальных форм.

Поведение symbol-function в целом определяется типом функции, которую содержит ее аргумент.

Функция symbol-function может вызываться с использованием в качестве аргумента любого символа, для которого предикат fboundp возвращает true. При этом стоит помнить, что fboundp возвращает true для символов, ссылающихся на макросы или на специальные формы.

Если fboundp возвращает true, но ее аргумент представляет собой макрос или специальную форму, то значение функции symbol-function является неопределенным, однако symbol-function не генерирует сообщение об ошибке.

В тех случаях, когда symbol-function используется совместно с setf, новое значение должно иметь тип function. Не допускается присваивать результат применения symbol-function символу, списку или значению, возвращенному symbol-function после применения к макросу или специальной форме.

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