Россия |
Запись Лисп-программ
Основные понятия, возникающие при написании программ – это переменные, константы, выражения, ветвления, вызовы функций и определения. Все они представимы с помощью списков.
- Самая простая форма выражения - это переменная. Имя переменной может быть представлено как атом. Переменная – это атом, имеющий значение.
X N Variable1 Переменная2 LongSong ДолгаяПесня4.1.
- Названия функций, как и имена переменных, изображаются с помощью атомов, для наглядности можно предпочитать заглавные буквы.
CONS CAR CDR ATOM EQ4.2.
- Все более сложные формы в Лиспе понимают как применение функции к ее аргументам (вызов функции). Аргументом функции может быть любая форма. Список, первый элемент которого – представление функции, остальные элементы - аргументы функции, – это основная конструкция в Лисп-программе.
Формат:
(функция аргумент1 аргумент2 ... )
(CONS 1 2 )4.3.
Обычно кроме базовых средств в язык включается и набор наиболее употребимых базовых операций над числами и другими данными. Если введены числа, то введены и традиционные арифметические операции, но форма их применения подчинена общим правилам:
(+ 1 2 3 4) ;; = 10
Формат:
(функция1 (функция2 аргумент21 аргумент22 ... ) аргумент2 ... )
(CAR (CONS 1 2 ) ) (CONS (CAR (CONS 1 2 ) ) (CDR (CONS 3 4 ) ))4.4.
Этих правил достаточно, чтобы более ясно выписать основные тождества Лиспа, формально характеризующие элементарные функции CAR, CDR, CONS, ATOM, EQ над S-выражениями:
(CAR (CONS x y)) = x (CDR (CONS x y)) = y (ATOM (CONS x y)) = Nil (CONS (CAR x) (CDR x)) = x для неатомарных x. (EQ x x) = T если x атом (EQ x y) = Nil если x и y различимы
Любые композиции заданного набора функций над конечным множеством произвольных объектов можно представить таким способом, но класс соответствующих им процессов весьма ограничен и мало интересен. Организация более сложного класса процессов требует более детального представления в программах соответствия между именами и их значениями или определениями, изображения ветвлений и объявления констант.
Специальные функции
- Константа представляется как аргумент специальной функции QUOTE в виде списка:
(QUOTE (C O N S T ))4.5. Список из атомов объявлен константой
Используется и сокращенная запись – апостроф перед произвольным данным.
'(C O N S T )4.6.
В зависимости от контекста одни и те же объекты могут выполнять роль переменных или констант, причем значения и того, и другого могут быть произвольной сложности. Если объект выполняет роль константы, то для объявления константы достаточно заблокировать его вычисление, то есть как бы взять его в кавычки (quotation), выделяющие буквальное использование фраз, не требующее обработки. Для такой блокировки вводится специальная унарная функция QUOTE, предохраняющая свой аргумент от вычисления.
(QUOTE A) | Константа A объявлена. |
(QUOTE (A B C) ) | Константа (A B C) объявлена. |
(ATOM (QUOTE A)) = T | Аргументом предиката "ATOM" является константа – атом "А" |
(ATOM (QUOTE (A B C) )) = Nil | Аргументом предиката является константа - список (A B C) |
(ATOM A) | Аргументом предиката "ATOM" является переменная – атом "А". Значение предиката не определено - оно зависит от вхождения переменной A, а ее значение зависит от контекста и должно быть определено или задано до попытки выяснить атом ли это. |
(третий (QUOTE (A B C))) | Применение новой функции к значению, не требующему вычисления, - константа (A B C). |
Упражнение. Запишите выражения, соответствующие применению функций из вышеприведенных определений.
- Построить функцию можно с помощью Lambda-конструктора:
(LAMBDA (x) (CAR (CDR (CDR x))) ) | |_____________________|_____определение функции | ___________________________ параметр функции4.8.
При вызове такой безымянной функции заодно происходит задание значений параметров - связанных переменных:
((LAMBDA (x) (atom x)) 123) ; = T
X получит значение 123 на время применения построенной безымянной функции, действие которой заключается в выяснении, атом ли аргумент функции.
Связанную переменную можно объявить специальной функцией Lambda, а значение она получит при вызове функции.
- Соответствие между названием функции и ее определением можно задать с помощью специального конструктора функций DEFUN, первый аргумент которого - имя функции, второй – собственно именуемое определение функции. Формальным результатом DEFUN является ее первый аргумент, который становится объектом другой категории. Он меняет свой статус – теперь это имя новой функции.
(DEFUN третий (x) (CAR (CDR (CDR x))) ) | | |__________________|_______ определение функции | |_____________________________ параметры функции |___________________________________ имя новой функции
Новая функция "третий" действует так же как " Caddr " в таблице 3.4.
Именование функций работает подобно заданию значений переменным. Идентификатор представляет структуру, символизирующую функциональный объект. В ней содержится список формальных параметров функции и тело ее определения – аргументы для лямбда-конструктора.
Обычно в рассуждениях о переменных и константах молчаливо подразумевается, что речь идет о данных. Разница между константами и переменными заключается лишь в том, что значение переменной может быть в любой момент изменено, а константа изменяется существенно реже. Лисп рассматривает представления функций как данные, поэтому функции могут быть как константными, так и переменными.
Представления функции могут вычисляться и передаваться как параметры или результаты других функций.
Соответствие между именем функции и ее определением может быть изменено, подобно тому, как меняется соответствие между именем переменной и ее значением.
- Ветвление (условное выражение) характеризуется тем, что ход процесса зависит от некоторых условий. Условия следует сгруппировать в общий комплект и соотнести с подходящими формами. Такую организацию процесса вычисления обеспечивает специальная функция COND (condition). Ее аргументами являются ветви, представленные как двухэлементные списки, содержащие предикаты и соответствующие им выражения. Количество ветвей не ограничено. Обрабатываются они по особой схеме: сначала вычисляются первые элементы аргументов по порядку, пока не найдется предикат со значением "истина". Затем выбирается второй элемент этого аргумента и вычисляется его значение, которое и считается значением всего условного выражения.
(COND (p1 e1) (p2 e2) ... (pk ek) ) |______|________|__________ предикаты для выбора ветви |______|____ ___|__________ ветви условного выражения
Каждый предикат pi или ветвь ei может быть любой формы: переменная, константа, вызов функции, композиция функций, условное выражение.
Обычное условное выражение (if Predicate Then Else) или (если Predicate то Then иначе Else) может быть представлено с помощью функции COND следующим образом:
(COND (Predicate Then)(T Else))
Или более наглядно:
(COND (Predicate Then ) (T Else ) )
Вычисление ряда форм в определении может быть обусловлено заранее заданными предикатами.
(COND ((EQ (CAR x) (QUOTE A)) (CONS (QUOTE B) (CDR x))) (T x) )4.9.
Атом " T " представляет тождественную истину. Значение всего условного выражения получается заменой первого элемента из значения переменной x на B в том случае, если (CAR x) совпадает с A.
Объявленные здесь специальные функции QUOTE, COND, LAMBDA и DEFUN существенно отличаются от элементарных функций CAR, CDR, CONS, ATOM, EQ правилом обработки аргументов. Обычные функции получают значения аргументов, предварительно вычисленные системой программирования по формулам фактических параметров функции.
Специальные функции не требуют такой предварительной обработки параметров.
Они сами могут выполнять все необходимое, используя представление фактических параметров в виде S-выражений.