
406
Глава 4. Метаязыковая абстракция
Однако тех же двух правил достаточно для решения следующих типов вопро сов, на
которые процедура ответить не может:
Найти список y, такой, что append (a b) и y дает (a b c d).
Найти все такие x и y, что append от н их дает (a b c d).
В языке логического программирования, когда программист пишет «процедуру» append,
он формулирует два правила, приведенные выше. Знание «как сделать» автоматически
обеспечивается интерпретатором, что позволяет использовать одну эту пару правил для
ответа на все три типа вопросов об append
60
.
У современных языков логического программирования (включая тот, который мы
сейчас реализуем) есть существенные недостатки, а именно: их общие методы «как
сделать» порой заводят в ненужные бе сконечные цикл ы или вызывают нежелательное
поведение другого рода. Логическое программирование сейчас активно исследуется в
информатике
61
.
Ранее в этой главе мы изучили технологию реализации интерпретаторов и описали те
ее элементы, которые необходимы в интерпретаторе Лисп-подобного языка (в сущности,
любого традиционного языка). Теперь мы воспользуемся этими идея ми при рассмотре-
нии интерпретатора для языка логического программирования. Мы называем этот язык
языком запросов (query language), поскольку он весьма удобен для извлечения инфор-
мации из баз данных при помощи запросов (queries), то есть выраженных на нашем
языке вопросов. Несмотря на то, что язык запросов сильно отличается от Лиспа, его
удобно обсуждать в терминах той же самой общей схемы, которую мы использовали
до сих пор: как набор элементарных составляющих, дополненных средствами комбини-
рования, которые позволяют нам сочетать простые составляющие и получать при этом
сложные, и средствами абстрак ции, которые позволяют нам рассматривать сложные со-
ставляющие как единые концептуальные единицы. Интерпретатор языка логического
программирован ия существенно сложнее, чем интерпретатор языка типа Лиспа. Тем не
менее, нам предстоит убедиться, что наш интерпретатор языка запросов содержит м но-
гие из тех же элементов, которые были в интерпретаторе из раздела 4.1. В частности,
у нас будет часть «eval», которая классифицирует выражения в соответствии с типом,
и часть « apply», которая реализует механизм абстракции языка (процедуры в случае
60
Это ни в коем случае не освобождает программиста полностью от решения задачи, как вычислить ответ.
Существует множество математически эквивалентных наборов правил для отношения append, и только неко-
торые из них можно превратить в эффективное средство для вычисления в каком-л ибо направлении. Вдобавок,
иногда информация «что такое» ничего не говорит о том, как вычислить ответ, — возьмем, например, задачу
найти такое y, что y
2
= x.
61
Пик интереса к логическому программированию пришелся на начало 80-х, когда японское правительство
инициировало амбициозный проект, целью которого было построение сверхбыстрых компьютеров, оптимизи-
рованн ых для логических языков программирования. Скорость таких компьютеров предполагалось измерять в
LIPS (Logical Inferences Per Second — число логических выводов в секунду), а не в обычных FLOPS (FLoating-
point Operations Per Second — число операций с плавающей точкой в секунду). Несмотря на то, что в рамках
проекта удалось создать аппаратное и программное обеспечение, которое изначально планировалось, интересы
международной компьютерной промышленности сместились в другом направлении. Обзор и оценку японского
проекта можно найти в Feigenbaum and Shrobe 1993. К тому же и в сообществе логических программистов
возник интерес к реляционному программирован ию на основе других методов, помимо простого сопоставления
с образцом, например, к работе с численными ограничени ями — вроде тех, которые присутствуют в системе
распространения ограничений из раздела 3.3.5.