На этом шаге мы разберем невычисляемые функции пользователя.
Использование макросредств, предлагаемых последними версиями muLISP (85 и 87), - один из самых эффективных путей реализации сложных программ. При наличии макросредств некоторые функции в языке могут быть определены в виде макрофункций. Такое определение фактически задает закон предварительного построения тела функции непосредственно перед фазой интерпретации.
К сожалению, в "младших" версиях muLISP (81 и 83) макросредства отсутствуют. Поэтому их приходится моделировать с помощью т.н. невычисляемых функций или NLAMBDA-функций.
NLAMBDA-функция ("No-spread LAMBDA") - специальный вид лямбда-выражения, обеспечивающий передачу параметров функции по имени.
Интерпретация невычисляемых функций производится в два этапа.
На первом, который мы будем называть макрорасширением, происходит формирование лямбда-определения функции в зависимости от текущего контекста, на втором осуществляется интерпретация созданного лямбда-выражения.
NLAMBDA-выражение имеет вид:
(NLAMBDA (X1 X2 ... XN) FN)
Первый аргумент функции NLAMBDA - (X1 X2 ... XN) является лямбда-списком (возможно, пустым!), X1, X2,...,XN - формальными параметрами.
Второй аргумент функции NLAMBDA (FN) - это тело. Оно представляет собой произвольное выражение, значение которого может вычислить интерпретатор языка LISP. Таким образом:
Рис.1. Вид NLAMBDA-выражения
Для того, чтобы применить NLAMBDA-функцию к аргументам, нужно в вызове
функции поставить NLAMBDA-выражение вместо имени функции (этим будет образован
лямбда-вызов):
( (NLAMBDA (X1 X2 ... XN) FN) A1 A2 ... AN)
Здесь Ai (i=1,2,...,N) - выражения языка LISP, определяющие фактические параметры.
Вычисление NLAMBDA-вызова (применение NLAMBDA-выражения к фактическим параметрам) производится следующим образом: формальные параметры связываются с соответствующими фактическими параметрами. Этот этап называется связыванием параметров.
На следующем этапе с учетом образованных связей вычисляется тело лямбда-выражения, и полученное значение возвращается в качестве значения лямбда-вызова. Формальным параметрам после окончания вычисления возвращаются те связи, которые у них были перед вычислением лямбда-вызова.
Весь этот процесс называют NLAMBDA-преобразованием.
Вывод. Если вычислять значения аргументов функции не нужно,
то такую функцию определяйте с помощью NLAMBDA-выражения. Например:
$ ((NLAMBDA (X) (CDR X)) (1 (TIMES 1 2) 4))
((TIMES 1 2) 4))
$ ((NLAMBDA (X) (CAR X)) ((TIMES 1 2) (PLUS 1 4)))
(TIMES 1 2)
$ (((NLAMBDA (X) (CAR X)) (PLUS TIMES)) 2 3)
(PLUS 2 3)
Однако заметим, что чрезмерное использование невычисляемых функций затрудняет чтение и понимание программ.
Следующий шаг будет посвящен поименованным функциям.