
- •3. Составные данные.
- •3.1 Списки. Часть I
- •Списком называют любую последовательность допустимых в lisPe элементов, заключенных в круглые скобки.
- •3.1.3 Функция append
- •3.1.4 Функция quote.
- •3.1.5 Функция eval
- •3.2 Точечные пары
- •3.3 Списки. Часть II
- •3.4 Две функции работы со списками
- •Лямбда-выражения и связывающие формы.
- •Для строгости определения приведем бнф для нотации
- •Примеры правильных - выражений:
- •Здесь X связывается с 3, а y остаётся свободной
- •Здесь z связывается с 5, остальные переменные оказываются свободными
- •3.5.1 Lambda – функция в Racket
- •3.5.2 Функция let и локальное -связывание
3. Составные данные.
3.1 Списки. Часть I
Списки играют в ЛИСПе главнейшую роль. По сути, в ЛИСПе нет ничего, кроме списков. Точнее кроме функций и списков. Функции – это активная составляющая программ, а списки – пассивная составляющая, т.е. данные.
Что такое лисповский список? Мы дадим несколько определений. Вот первое из них.
Списком называют любую последовательность допустимых в lisPe элементов, заключенных в круглые скобки.
3.1.1 Функция list
Для получения списков специально существует функция list.
Её формат
(list x1 … xn) создаёт список, который будет состоять из значений перечисленных элементов (x1 … xn).
Примеры
> (list 1 "Привет" 3)
(1 "Привет" 3)
Появляется просто список элементов.
> (list '+ 1 2)
(+ 1 2)
Это уже не просто список, а нечто похожее на вызов функции сложения. Так в действительности и есть, только пока нечем заставить это сложение выполнится.
Внутренне, списки представляются последовательностью пар, в которых каждая первая часть это значение элемента, а вторая её часть – ссылка на следующую пару. К примеру, последний полученный список графически будет выглядеть так:
Список предваряет ссылка на его начало, а в последней паре ссылка отсутствует (на самом деле её значение приравнивается к NIL) .
Существует особый список, составленный из пустого множества элементов, который так и называется - пустой список, по-другому – это список из «НИЧЕГО», т.е. последовательность двух парных круглых скобок
> (list )
()
Традиционно в ЛИСПе пустой список обозначается атомом NIL (сокращение от латинского nihil – ничто.
ВАЖНО: в Racket такого атома нет!
Список можно образовать из двух и более подсписков
> (list '(1 2) '(3 4))
((1 2) (3 4))
Графически это будет так:
До После
Очень важно всегда помнить, что список образуется из значений!!
> (list a 2)
reference
to undefined identifier: a
> (define a -3)
> (list a 2)
(-3 2)
Функция List – это не единственная функция, результатом которой является список. Она просто – узко специализирована.
3.1.2 Функции car и cdr
Для работы с частями списка существуют две стандартные и, на первый взгляд, очень странно названные функции car и cdr.
(car lst) возвращает первый элемент списка lst.
(cdr lst) возвращает остаток списка, т.е. список lst, из которого выброшен первый элемент.
Примеры
> (car (list 1 2 3))
1
> (cdr (list 1 2 3))
(2 3)
Из рисунка видно, что результатом действия CDR является ссылка, т.е. указатель на список (из остатка).
Путешествие по списку можно продолжить:
> (car (cdr (list 1 2 3)))
2
> (car (cdr (cdr (list 1 2 3))))
3
Так почему же они так странно называются? Казалось бы, проще было бы назвать их по смыслу, например – first и rest.(Некоторые реализации lisp’а так и поступают). И мы, конечно, можем определить синонимы для этих функций (ещё одно интересное назначение функции define), например так:
> (define head car)
> (define tail cdr)
> (head (list 1 2 3 4))
1
> (tail (list 1 2 3 4))
(2 3 4)
Но в целях совместимости и для того, чтобы привыкнуть и легко читать другие программы, написанные на LISPe, мы всё-таки будем использовать исконно лисповские названия.
Эти имена унаследованы от первоначальной реализации Лиспа на IBM 704. Та машина имела схему адресации, которая задавалась двумя регистрами, отдельно частью «адреса» и частью «декремента» (т.е. смещения относительно «адреса»), которые имели такие названия:
CAR - аббревиатура от «Contents of Address part of Register»
CDR - от «Contents of Decrement part of Register»
Интересно, что существуют и «производные» от этих названий вида cadr, caddr и т.п. В таких «жутких» названиях, на самом деле, очень удачно указывается процесс «подползания» к соответствующим элементам списка, правда, существует ограничение:
Количество букв A и D, записываемых между начальной C и конечной R не больше четырех.
Примеры использования комбинаций. (Сравните с предыдущими примерами)
> (cadr (list 1 2 3))
2
> (caddr (list 1 2 3))
3