4.3.2.
Структура LISP-программы
Как использовать
список в качестве базовой структуры данных, понятно. Сложнее представить себе,
как можно организовать программу или выражение программы в виде списка.
Например, список
(+ X Y) представляет
математическое выражение в форме
(<функция>
<1-й аргумент> <2-й аргумент>),
которое обозначает
сложение двух чисел. Такой метод обозначений (нотация) отличается от привычного
нам обозначения функции п переменных в виде f(x1, ... xn).
Но возникает вопрос, как компилятор или интерпретатор отличает данные от программы,
если и то и другое представлено списками.
((1
2 3)(4 5 6)(7 8 9))
и пытаться
отыскать определение функции (1 2 3).
Для этого
существует специальная форма выражения (QUOTE X) для любых X, которая возвращает
X. Точно такое же действие выполняется и выражением (quote X).
Современные
версии LISP не чувствительны к регистру символов, хотя и возможно так сконфигурировать
исполнительную систему, что она станет по-разному воспринимать символы верхнего
и нижнего регистров.
4.3.
Функции, их вычисление и проблема цитирования в CLIPS
Существуют
два основных метода разрешения проблемы цитирования, т.е. предотвращения интерпретации
данных как функций или выражений. Один метод заключается в том, чтобы в число
системных функций ввести специальную функцию, которая рассматривается интерпретатором
как указание не обрабатывать последующий список. Такой системной функцией в
LISP является QUOTE. Другой метод состоит в том, чтобы по умолчанию
подавлять механизм оценивания значения (вычисления) до тех пор, пока специальная
синтаксическая конструкция его не запустит. В языке CLIPS использован именно
такой метод.
Например,
в CLIPS можно следующим образом определить функцию:
(deffunction between(?lb ?value ?ub)
(or
(> lib ?value) (> ?value ?ub))))
Эта
функция определяет, попало ли заданное целочисленное значение в диапазон между
указанными нижним и верхним пределами. Знак вопроса, предшествующий именам,
говорит интерпретатору CLIPS, что выражения ?lb, ?value и ?ub являются переменными
и их не нужно оценивать.
Общепринятым методом реализации функциональных языков типа LISP является использование четырехстековой машины, за которой закрепилось наименование SECD-машины. В четырех стеках машины отслеживаются промежуточные результаты, значения переменных, текущее выражение и копии текущего состояния процесса вычислений сложного выражения, которые нужны, чтобы восстановить состояние после завершения вычисления вложенного выражения (подвыражения). Не вдаваясь в подробности, отметим, что процесс оценивания символического выражения в такой машине — это не что иное, как реализация базовой операции приложения функции, как это определено в лямбда-исчислении (см., например, [Henderson, 1980], [Glaser et al., 1984]).