Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лисп.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.66 Mб
Скачать

13 . Внутреннее представление списков в Лиспе

Списочная ячейка состоит из двух частей, полей CAR и CDR. Каждое из полей содержит указатель. Указатель может ссылаться на другую списочную ячейку или на некоторый другой лисповский объект, как, например, атом. Указатели между ячейками

образуют как бы цепочку, по которой можно из предыдущей ячейки попасть в следующую и так, наконец, до атомарных объектов.

Значение представляется указателем

Указателем списка является указатель на первую ячейку списка. На ячейку могут указывать не только поля CAR и CDR других ячеек, но и используемый в качестве переменной символ, указатель из которого ссылается на объект, являющийся значением символа. Указатель на значение хранится Указатель на значение хранится вместе с символом в качестве его системного свойства.

Побочным эффектом функции присваивания SETQ является замещение указателя в поле значения символа. Например, следующий вызов:

создает в качестве побочного эффекта изображенную штриховую стрелку.

Если мы применим функцию CAR к списку СПИСОК, то результатом будет содержимое

левого поля первой списочной ячейки, т.е. символ А:

Допустим, что у нас есть два списка:

Вызов функции

строит новый список из ранее построенных списков ГОЛОВА и ХВОСТ так

CONS создает новую списочную ячейку. Содержимым левого поля новой ячейки станет значение первого аргумента вызова, а

правого - значение второго аргумента. Обратите внимание, что одна новая списочная ячейка может связать две большие структуры в одну новую структуру. Это довольно эффективное решение с точки зрения

создания структур и их представления в памяти. Заметим, что применение функции CONS не изменило структуры списков, являющихся аргументами, и не изменило значений переменных ГОЛОВА и ХВСХИТ.

Если элементами списка являются не атомы, а подсписки, то на месте атомов будут находится первые ячейки подсписков.

Из этого рисунка видно, что логически идентичные атомы содержатся в системе один раз, однако логически идентичные списки могут быть представлены различными списочными ячейками.

являются логически одинаковым списком (В С), хотя они и представлены различными списочными ячейками.

Предикат EQ можно использовать лишь для сравнения двух символов. Предикат EQ обобщен таким образом, что с его помощью можно определить физическое равенство 2-х

выражений двух выражений не зависимо от того, является ли он атомом или списком.

Название точечной пары происходит из использованной в ее записи точечной нотации, в

которой для разделения полей CAR и CDR используется выделенная пробелами точка:

Выражение слева от точки соответствует значению поля CAR списочной ячейки, а выражение справа от точки - значению поля CDR. Базовые функции CAR и CDR действуют совершенно симметрично:

Точечная нотация позволяет расширить класс объектов, изображаемых с помощью списков.

Управление памятью и сборка мусора

В результате вычислений в памяти могут возникать структуры, на которые потом нельзя сослаться. Это происходит в тех случаях, когда вычисленная структура не сохраняется с помощью SETQ или когда

теряется ссылка на старое значение в результате побочного эффекта нового вызова SETQ или другой функции.

Для повторного использования ставшей мусором памяти предусмотрен специальный мусорщик, который автоматически запускается, когда в памяти остается мало свободного

места. Мусорщик перебирает все ячейки и собирает являющиеся мусором ячейки в список свободной памяти для того, чтобы их можно было использовать заново.

Специальные функции, при помощи которых на структуры уже существующих выражений можно непосредственно влиять называют структуро-разрушающими, поскольку с их помощью можно разорвать структуру и склеить ее по-новому.

Основными функциями, изменяющими физическую структуру списков, являются RPLACA и RPLACD, которые уничтожают прежние и записывают новые значения в поля CAR и CDR

списочной ячейки.

Функция RPLACD выполняется так же, как RPLACA, с той разницей, что меняется значение поля CDR:

Разумно использованные структуро-разрушающие функции могут быть эффективными и полезными инструментами. Далее мы для примера рассмотрим, как можно с помощью структуроразрушающих псевдофункций повысить эффективность лисповской функции APPEND, APPEND объединяет в один список списки, являющиеся его аргументами:

Может показаться, что приведенный выше вызов APPEND, как бы изменяет указатеяи так, как это показано штриховыми стрелками.

Однако это не верно, так как значение списка НАЧАЛО не может измениться, поскольку APPEND не является структуроразрушающей функцией. Вычисляется и присваивается лишь новое значение переменной

РЕЗУЛЬТАТ. Мы получим структуры

APPEND создает копию списка, являющегося первым аргументом. Если этот список очень

длинный, то долгими будут и вычисления.

Если для нас не существенно, что значение переменной НАЧАЛО изменится, то мы

можем вместо функции APPEND использовать более быструю функцию NCONC. Функция NCONC просто объединяет списки, изменяя указатель в поле CDR последней ячейки списка, являющегося первым аргументом, на начало списка, являющегося вторым

аргументом.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]