
394
Глава 4. Метаязыковая абстракция
заканчивалась успехом и порождала подход ящее слово, мы сможем использовать те же програм-
мы, ко торые мы написали для анализа, для порождения предложений. Реализуйте идею Лизы и
покажите первые пять-шесть порожденных предложений
54
.
4.3.3. Реализация amb-и нт ерпретатора
Выполнение выражения в обыкновенной Scheme может вернуть результат, может
вообще не завершиться, и, наконец, может закончиться сообщением об ошибке. В неде-
терминистской Scheme при выполнении выражения, в дополнение ко всему этому, может
еще обнаружиться тупик, и в этом случае вычисление должно откатиться к предыду-
щей точке выбора. Интерпретация недетерминистской Scheme осложняется из-за этой
дополнительной возможно сти.
Мы построим amb-интерпретатор для недетерминистской Scheme, модифицировав
анализирующий интерпретатор из раздела 4.1.7
55
. Как и в анализирующем интерпр етато -
ре, вычисление выражения происходит путем вызова исполнительной процедуры, которая
получается при анализе этого выражения. Разница между интерпретацией обыкновен-
ной Scheme и недетерминистской Scheme будет полностью сводиться к исполнительным
процедурам.
Исполнительные процедуры и продолжения
Напомним, ч то исполнительные процедуры обыкновенного интерпретатора принима-
ют один аргумент: окружение, в котором происходит вычисление выражения. В противо-
положность этому, исполнительные процедуры amb-интерпретатора принимают три аргу-
мента: окружение и две процедуры, называемые процедурами продолжения (continuation
procedures). Вычисление выражения будет заканчиваться вызовом одного из этих про-
должений: если резул ьтатом вычисления является значение, то зовется продолжение
успеха (success continuation) с этим значением в качестве аргумента; если вычисление
натыкается на тупик, вызывается продолжение неудачи (failure continuation). Построе-
ние и вызов соответствующих продолжений служит механизмом, с помощью которого в
недетерминистском интерпретаторе реализуется поиск с возвратом.
Задача продол жения успеха — принять значение и продолжить вычисление. Помимо
этого значения, продолжение успеха получает дополнительное продолжение неудачи,
которое нужно будет вызвать, если использование значения приведет в тупик.
Задача продолжения неудачи — попробовать другую ветвь неде терминистского про-
цесса. Главная особенность недетерминистского языка состоит в том, что выражения
могут представлять собой точки выбора между вариантами. Выполнение такого выраже-
ния должно продолжиться согласно одному из указанных взаимоисключающих вариан-
тов, несмотря на то, что заранее неизвестно, какие варианты приведут к приемлемым
54
Несмотря на то, что идея Лизы (будучи удивительно простой) дает результат, порождаемые предложения
оказываются довольно скучными — они не отображают возможные предложения нашего языка никаким инте-
ресным образом. Дело в том, что грамматика рекурсивна во многих местах, а метод Лизы «проваливается» в
одну из рекурсий и там застревает. Как с этим можно бороться, Вы увидите в упражнении 4.50.
55
В разделе 4.2 мы решил и реализовать ленивый интерпретатор как модификацию обыкновенного метацик-
лического интерпретатора из раздела 4.1.1. Напротив, здесь в основу amb-интерпретатора мы кладем анализи-
рующий интерпретатор из раздела 4.1.7, поскольку исполнительные процедуры этого интерпретатора служат
удобной базой для реализации поиска с возвратом.