Имена и контексты
Программы для Лисп-интерпретатора.
Цель этой части - помочь на первых шагах избежать некоторых общих ошибок.
(CAR '(A B)) = (CAR (QUOTE(A B)))8.2.
Аргументы: ((A B))
Значение есть A. Заметим, что интерпретатор ожидает список аргументов. Единственным аргументом для CAR является (A B). Добавочная пара скобок возникает т.к. APPLY подается список аргументов.
Можно написать (LAMBDA(X)(CAR X)) вместо просто CAR. Это корректно, но не является необходимым.
(CONS 'A '(B . C))8.3.
Аргументы: (A (B . C))
Результат (A . (B . C)) программа печати выведет как (A B . C)
(CONS '(CAR (QUOTE (A . B))) '(CDR (QUOTE (C . D))) )8.4.
Аргументы: ((CAR (QUOTE (A . B))) (CDR (QUOTE (C . D))))
Значением такого вычисления будет ((CAR (QUOTE (A . B))) . (CDR (QUOTE (C . D))))
Скорее всего это отнюдь не то, что ожидал новичок. Он рассчитывал вместо (CAR (QUOTE (A . B)) получить A и ожидал (A . D) в качестве итогового значения CONS. Кроме очевидного стирания апострофов:
(CONS (CAR (QUOTE (A . B))) (CDR (QUOTE (C . D))) )
ниже приведены еще три правильных способа записи нужной формы. Первый состоит в том, что CAR и CDR части функции задаются с помощью LAMBDA в определении функции. Второй - в переносе CONS в аргументы и вычислении их с помощью EVAL при пустом а-списке. Третий - в принудительном выполнении константных действий в представлении аргументов,
((LAMBDA (X Y) (CONS (CAR X) (CDR Y))) '(A . B) '(C . D))
(LAMBDA (X Y) (CONS (CAR X) (CDR Y)))
Аргументы:
((A . B)(C . D))
(EVAL '(CONS (CAR (QUOTE (A . B))) (CDR (QUOTE (C . D)))) Nil)
Аргументы:
((CONS (CAR (QUOTE (A . B))) (CDR (QUOTE (C . D)))) Nil)
Значением того и другого является (A . D)
((LAMBDA (X Y) (CONS (EVAL X) (EVAL Y))) '(CAR (QUOTE (A . B))) '(CDR (QUOTE (C . D))) )
(LAMBDA (X Y) (CONS (EVAL X) (EVAL Y)))
Аргументы:
((CAR (QUOTE (A . B))) (CDR (QUOTE (C . D))))
Решения этого примера показывают, что грань между функциями и данными достаточно условна - одни и те же вычисления можно осуществить при разном распределении промежуточных вычислений внутри выражения, передвигая эту грань.
(Defconstant Атом Форма ) | Глобальная константа |
(Defparameter Атом Форма ) | Глобальная переменная |
(Defun Название Параметры Форма ) | Определение функции |
(Flet ((Название Параметры Форма) … (Спецификации … Формы …)) | Вводит локальные нерекурсивные функции |
(Labels ( (Название Параметры Форма) … (Спецификации … Формы …) ) | Вводит локальные рекурсивные функции |
Выводы:
- Чтобы выполнить вычисление на реальном Лисп-интерпретаторе необходимо уточнить ряд правил по оформлению текста Лисп-программы.
- Определения функций можно сделать обозримее именованием выражений. Это дает и экономию на времени вычисления совпадающих форм.
- При реализации практичной системы программирования возникают дополнительные механизмы, такие как списки свойств атома, повышающие скорость доступа к необходимой информации.
- Некоторые функции системы необходимо реализовывать в виде машинных подпрограмм. Они образуют ядро системы.
- При подготовке программ для Лисп-интерпретатора грань между программой и данными может устанавливаться в зависимости от требований к решению задачи.