На этом шаге мы разберем как можно создавать поименованные функции.
С помощью аппарата лямбда-выражений в языке LISP можно определить поименованные функции. Для этой цели необходим конструктор функций, осуществляющий связывание атома (имени функции) с лямбда-выражением. Результат связывания называется LAMBDA- или NLAMBDA-определением функции. В качестве таких конструкторов выступают PUTD и DEFUN.
Функция PUTD, имеющая два аргумента, связывает атом, являющийся первым аргументом
с LAMBDA- или NLAMBDA-выражением, выступающим в качестве второго
аргумента, и возвращает в качестве своего значения имя определяемой функции. Например:
$ (PUTD FOO (LAMBDA (X Y) (CONS X Y)))
FOO
Теперь, определив новую функцию FOO, мы можем обращаться к ней так:
$ (FOO A B)
(A . B)
Отметим, что основным назначением функции PUTD является не только возвращение имени функции, но и связывание его с некоторым определением.
Для доступа к определениям предназначена функция GETD одного аргумента (имя
функции), которая возвращает лямбда-определение данной функции. Например:
$ (GETD FOO)
(LAMBDA (X Y) (CONS X Y))
И, наконец, функция MOVD присваивает функциональное значение, связанное с
первым атомом, второму атому. Например:
$ (MOVD FOO BOO)
(LAMBDA (X Y) (CONS X Y))
1. Если SYMBOL есть функция, определенная пользователем, то функция (GETD SYMBOL) декомпилирует и возвращает определение символа SYMBOL в виде списка.
Если SYMBOL является простой функцией или специальной формой, то функция (GETD SYMBOL) возвращает адрес в физической памяти шаблона функции на машинном языке.
Если SYMBOL не является специальной формой или функцией, то функция (GETD SYMBOL) возвращает NIL.
Если FLAG не является NIL, то функция (GETD SYNBOL FLAG) возвращает:
2. Функция (PUTD SYMBOL DEFINITION) компилирует определение DEFINITION
в D-код, модифицирует элемент определения функции SYMBOL на указание на компилируемый
D-код и возвращает SYMBOL. Например:
$ (PUTD 'SQUARE '(LAMBDA (NUM) (* NUM NUM)))
SQUARE
$ (SQUARE 5)
25
Обьекты, не являющиеся атомами (константы), в определении функции не компилируются, но остаются сохраненными как связанный список. Следовательно, в отличие от более ранних версий, интерпретатор muLISP85 не должет декомпилировать такие константы каждый раз, как они встречаются, и константы могут содержать точечные пары с CDR-элементами, являющимися не NIL-атомами.
Управляющая переменная PUTD управляет сжатием D-кода во время компиляции.
Управляющая переменная MACROEXPAND управляет макрорасширением во время компиляции.
Для связи с определенными пользователем шаблонами на машинном языке функция PUTD вызывается с DEFINITION, равным адресам в физической памяти этих шаблонов.
3. Функция (MOVD SYMBOL1 SYMBOL2) передает определение функции от SYMBOL1 к SYMBOL2 и возвращает SYMBOL2.
На примерах показано, как можно использовать MOVD для присваивания других
мнемонических имен некоторым функциям селектора LISP без ущерба для эффективности
их выполнения.
$ (MOVD 'CAR 'FIRST)
FIRST
$ (MOVD 'CDR 'REST)
REST
$ (MOVD 'CADR 'SECOND)
SECOND
$ (MOVD 'CADDR 'THIRD)
THIRD
$ (MOVD 'CADDDR 'FOURTH)
FOURTH
$ (FIRST '(A B C D))
A
4. Функция (REMD SYMBOL) модифицирует элемент определения функции SYMBOL,
делая SYMBOL неопределенным. Функция REMD возвращает SYMBOL. Например:
$ (PUTD 'SWITCH '(LAMBDA (SYM1 SYM2) (CONS SYM2 SYM1)))
$ (SWITCH 'DOG 'CAT)
(CAT . DOG)
$ (REMD 'SWITCH)
SWITCH
$ (GETD 'SWITCH)
NIL
$ (SWITCH 'DOG 'CAT)
Undefined Function
5. Когда определение функции скомпилировано, то осуществляется поиск существующих эквивалентов D-кода для каждого подвыражения в определении. Если такой эквивалент D-кода найден, то он используется вместо дальнейшего создания D-кода, в связи с чем экономится память. Этот процесс называется конденсацией.
Если управляющая переменная PUTD - не NIL, то поиск при конденсации ограничен собственным D-кодом определения. Хотя при этом увеличивается обьем используемой под D-код памяти, ограничение на область поиска значительно уменьшает время на чтение и компиляцию файлов, содержащих большое количество определений функций.
Если PUTD есть NIL, поиск при конденсации охватывает все существующие D-коды. Это уменьшает обьем памяти, требуемый для хранения данного количества определений функций, но зато увеличивает время на компиляцию определений функций.
Когда функция, определенная пользователем, переопределена с помощью PUTD или
MOVD, или ее определение удалено с помощью REMD, D-код, используемый
для хранения определения, автоматически переутверждается, если полная конденсация
не была выполнена (если PUTD не был равен NIL).
На следующем шаге мы продолжим знакомство с поименованными функциями.