Использование переменных в качестве объектов
Нетривиальная проблема, связанная с явной обработкой переменных при определении отношения occurs_in в предыдущем разделе, подчеркивает слабость выразительных средств Пролога. Работа с переменными связана с некоторыми сложностями, и при анализе и обработке термов между переменными и значениями могут возникнуть случайные соответствия.
Такая проблема появляется при построении программы 9,3, определяющей отношение Substitute. Рассмотрим цель Substitute (a, b, X, Y), задающую подстановку константы а вместо b в переменную X. Результатом подстановки является терм Y. Имеются две правдоподобные интерпретации отношения Substitute в этом случае. Логически обоснованным решением является сопоставление переменной Х константы а, а переменной Y – константы b. Это решение действительно находится программой 9.3 при унификации цели с основным фактом Substitute (Оld, New, Old, New).
Однако на практике предпочтительнее иная интерпретация. Будем считать термы Х и а различными; таким образом, переменной Y следует сопоставить терм X. При такой интерпретации следовало бы воспользоваться другим предложением программы 9.3, а именно:
Substitute(01d, New, Term, Term)¬ constant(Terrn),Term¹ Old.
Цель, однако, не будет доказана, так как переменная не является константой.
Мы можем избежать первого (логического) решения, используя металогический тест, гарантирующий подстановку в основной терм. Тогда неявная унификация с заголовком предложения становится выполняемой лишь в случае, если тест выполнен. Следовательно, унификация должна быть задана явно. Основной факт превращается в правило:
Substitute(01d, New, Term, New)¬ ground(Term),Term = Old.
Рассмотрение переменных отдельно от констант требует специального правила также использующего металогический тест:
Substitute(01d,New,Var,Var)¬var(Var).
Добавление двух рассмотренных предложений к программе 9.3, определяющей отношение Substitute, а также добавление других металогических тестов позволяет применять программу к неосновным термам. Однако полученная программа будет громоздкой. В ней смешаны процедурный и декларативный подходы. Для понимания такой программы требуется знание механизма управления, реализованного в Прологе. Используя аналогию с медициной, можно сказать, что мы лечим симптомы (нежелательное сопоставление значения переменной), а не болезнь (отсутствие средств, позволяющих использовать переменные в качестве объектов). Для “исцеления” необходимы дополнительные металогические примитивы.
Сложности, возникающие при смешивании обработки термов на метауровне и на объектном уровне, связаны с некоторой теоретической проблемой. Строго говоря программы метауровня должны рассматривать переменные объектного уровня как константы и должны иметь возможность ссылаться на такие переменные по имени,
Расширяя Пролог двумя системными предикатами: freeze (Term, Frozen) и melt (Frozen,Thawed), можно частично решить указанные проблемы. “Замораживание”
терма Term с помощью предиката freeze создает копию терма Frozen. В этом терме все переменные исходного терма, которым не были сопоставлены значения, заменяются уникальными константами. Замороженный терм подобен основному терму и может использоваться так же, как и основной терм.
При унификации замороженные переменные рассматриваются как основные атомы. Две замороженные переменные унифицируемы тогда и только тогда, когда они совпадают. Аналогично, если переменная, которой не сопоставлено значение, унифицируется с замороженным термом, то значением переменной становится замороженный терм. Применение системного предиката к замороженной переменной приводит к тому же результату, что и применение к константе. Например, использование замороженных переменных в арифметических вычислениях приводит к безуспешным вычислениям.
Предикат freeze, как и предикат var, является металогическим предикатом. Он позволяет анализировать структуру терма непосредственно в процессе вычисления.
Наличие предиката freeze позволяет иначе определить предикат occurs_in, рассматривавшийся в предыдущем разделе. Идея состоит в замораживании терма, что превращает переменные в основные обекты. Это позволяет использовать программу Subterm (программа 9.2), правильно обрабатывающую основные термы. Метод реализован в программе 10.7(b).
Замораживание позволяет решать вопрос идентичности двух термов. Два замороженных терма Х и Y унифицируемы тогда и только тогда, когда их незамороженные варианты идентичны, т. е, когда Х = = Y. Это свойство существенно для обоснования корректности программы 10.7(b).
Отличие замороженных термов от основных состоит в том, что замороженные термы можно “разморозить”, превратив их в неосновные термы. Предикатом, двойственным к freeze, является предикат melt (Frozen,Thawed). Вычисление цели melt (X, Y) создает копию терма Y терма X, в которой замороженные переменные становятся обычными переменными языка Пролог. При размораживании терма Y учитываются все сопоставления значений переменным терма X, сделанные пока терм был заморожен.
Freeze заморозить, melt разморозить. – Прим. перев.
Далее дается без кавычек. -Прим. ред.
Используя предикаты freeze и melt, можно построить вариант программы substitute, а именно non_ground_substitute, в котором не происходит нежелательных сопоставлений значений переменным. Процедурный подход к программе поп_ ground_substitute состоит в следующем: перед подстановкой терм замораживается; далее, используя программу substitute, правильно обрабатывающую основные термы, производится подстановка в замороженный терм; наконец, новый терм размораживается:
non_ground_substitute (X, Y, Old, New)¬
freeze(0ld,0ld1),
substitute(X,Y,Old,Old1),melt(Old, New).
Замороженный терм можно также использовать как шаблон для изготовления копий. Системный предикат melt_new (Frozen, Term) создает копию Term терма Frozen, в которой замороженные переменные заменены переменными с новыми именами.
Предикат melt_new используется для копирования термов. Предикат copy(Term, Copy) создает новую копию терма Term. Этот предикат можно задать одним правилом:
copy (Term, Copy)¬freeze (Term, Frozen), melt_new(Frozen,Copy).
Примитивы freeze, melt и melt_new полезны при задании вводимых в гл. 12 внелогических предикатов и описании их вычислений.