Опубликован: 19.03.2004 | Уровень: специалист | Доступ: платный
Лекция 6:

Свойства атомов и категории функций

< Лекция 5 || Лекция 6: 12345 || Лекция 7 >

Деструктивные (разрушающие) преобразования структуры списков

Теория рекурсивных функций, изложенная в лекции 2, будет упоминаться далее как строгий, чистый или элементарный Лисп. Хотя этот язык универсален в смысле теории вычислимых функций от символьных выражений, он непрактичен как система программирования без дополнительного инструмента, увеличивающего выразительную силу и эффективность языка.

В частности, элементарный Лисп не имеет возможности модифицировать структуру списка. Единственная базисная функция, влияющая на структуру списка — это CONS, а она не изменяет существующие списки, только создает новые. Функции, описанные в чистом Лиспе, такие как SUBST, в действительности не модифицируют свои аргументы, но делают модификации, копируя оригинал.

Элементарный Лисп работает как расширяемая система, в которой информация как бы никогда не пропадает. SET внутри PROG лишь формально смягчает это свойство, сохраняя ассоциативный список и моделируя присваивания теми же CONS.

Теперь же Лисп обобщается с точки зрения структуры списка добавлением структуроразрушающих средств — деструктивных базисных операций над списками RPLACA и RPLACD. Эти операции могут применяться для замены адреса или декремента любого слова в списке. Они используются ради их действия так же, как и ради их значения и называются псевдо-функциями.

(RPLACA x y) заменяет адрес из x на y, эквивалент (CAR x) := y. Ее значение — x, но x, несколько отличающийся от того, что было раньше. На языке значений RPLACA можно описать равенством

(RPLACA x y) = (CONS y (CDR x))

Но действие различное: никакие CONS не вызываются и новые слова не создаются.

(RPLACD x y) заменяет декремент x на y, эквивалент (CDR x) := y.

Эти операции должны применяться с осторожностью! Они могут в корне преобразить существующие определения и основную память. Их применение может породить циклические списки, приводящие к бесконечной печати или выглядящие бесконечными для таких функций как EQUAL и SUBST.

Деструктивные функции используются при реализации списков свойств атома и ряда эффективных, но небезопасных, функций Clisp, таких как NCONC, MAPC и т.п.

Для примера рассмотрим функцию MLTGRP. Это преобразующая список функция, которая преобразует копию своего аргумента. Подфункция GRP реорганизует подструктуру

подструктура

Рис. 1.13. подструктура

в структуру из тех же атомов:

структура из тех же атомов

Рис. 1.14. структура из тех же атомов

Исходная функция делает это, создавая новую структуру и используя четыре CONS. Из-за того, что в оригинале только три слова, по крайней мере, один CONS необходим, а GRP можно переписать с помощью RPLACA и RPLACD. Изменение состоит в следующем:

новая структура

Рис. 1.15. новая структура

Пусть новое машинное слово строит (CONS (CADR x) (CDDR x)). Тогда указатель на него встраивается в x при вычислении формы:

(RPLACA (CDR x) (CONS (CADR x) (CDDR x)))

Другое изменение сводится к удалению из второго слова указателя на третье слово.

Это выполняется как вычисление формы (RPLACA (CDR x) NIL).

Функция PGRP теперь определяется как соотношение:

(PGRP x) = (RPLACD (RPLACA (CDR x) (CONS (CADR x)
   (CDDR )x))) NIL)

Функция PGRP используется, в сущности, ради ее действия. Ее значением, неиспользуемым, является подструктура ((B C)). Поэтому для MLTGRP необходимо, чтобы PGRP выполнялось, а ее значение игнорировалось. Поскольку верхний уровень не должен копироваться, MLTGRP не обязана основываться на CONS.

(PMLTGRP L) =(COND ((NULL L) NIL)
                             (T (PROG2 (PGRP (CDR L))
                                      (PMLTGRP (CDR L)) )))

PROG2 — функция, вычисляющая свои аргументы. Ее значение — второй аргумент.

Значение PMLTGRP — NIL, PGRP и PMLTGRPпсевдо-функции.

Список свободной памяти и сборщик мусора

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

Первые реализации действовали по следующей схеме [ 1 ] .

Определенный регистр FREE содержит информацию о первой ячейке этого списка. Когда требуется слово для формирования дополнительной структуры списка, берется первое слово списка свободной памяти, а код в регистре FREE заменяется на информацию о втором слове списка свободной памяти. Не требуется никаких программных средств для того, чтобы пользователь программировал возврат ячеек в список свободной памяти. Этот возврат происходит автоматически при пропуске программы, где бы ни исчерпался список свободной памяти. Программа, восстанавливающая память, называется "мусорщик" . Любая часть структуры списка, доступная программе, рассматривается как активный список и не затрагивается мусорщиком. Активные списки доступны программе через некоторые фиксированные наборы базисных ячеек, таких как ячейки списка атомов и ячейки, вмещающие частичные результаты Лисп-выражений. Сложные структуры списков могут быть произвольной длины, но каждое активное слово должно быть подведено к базисной ячейке цепью CAR-CDR.

Любая ячейка, не достижимая таким образом, недоступна для программы и не активна, поэтому ее содержимое не представляет интереса. Неактивные, то есть недоступные программе ячейки восстанавливаются мусорщиком в списке свободной памяти следующим образом. Во-первых, каждая ячейка, к которой можно получить доступ через цепь CAR-CDR, метится установлением отрицательного знака. Где бы ни выявилось отрицательное слово в цепи во время процесса пометки, мусорщик знает, что остаток раскручиваемого списка содержит уже помеченные ячейки. Затем мусорщик предпринимает линейное выметание осовободившегося пространства, собирая ячейки с положительным знаком в новый список свободной памяти и восстанавливая исходный знак активных ячеек.

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

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

Такая реализация экономична в отношении памяти, но она имеет ряд неприятных следствий: непредсказуемые длинноты (время работы) при поиске очередной порции ячеек и "перегрев системы", если такие порции слишком малы для продолжения счета. По мере роста производительности оборудования разработаны простые и не столь обременительные алгоритмы повторного использования памяти на базе параллельных процессов и профилактического копирования активных структур данных в дополнительные блоки памяти. Такие методы не требуют сложной разметки и анализа достижимости. Содержательная аналогия с мастерским мытьем посуды, то есть не допуская переполнения раковины, вполне отражает метод stop&copy; принятый в современных реализациях.

< Лекция 5 || Лекция 6: 12345 || Лекция 7 >
Дарья Федотова
Дарья Федотова
Сергей Березовский
Сергей Березовский

В рамках проф. переподготовки по программе "Программирование"

Есть курсы, которые я уже прошел. Но войдя в курс я вижу, что они не зачтены (Язык Ассемблера и архитектура ЭВМ, Программирование на С++ для профессионалов). Это как?

Алина Ленкова
Алина Ленкова
Россия, Ставрополь, СФ МГУПИ, 2014
Валерий Ромашов
Валерий Ромашов
Россия