get(X):- new_get(X), X › 32.
Чтобы понять это определение, нужно вспомнить, что в кодировке ASCII все неуправляющие (печатаемые) литеры имеют код, превышающий 32, все остальные литеры имеют код, меньший или равный 32. Что происходит при попытке согласовать get(X)?Прежде всего new_get(X)сопоставляет X с текущей литерой, введенной в систему. Если ее код меньше или равен 32, то следующее целевое утверждение неверно и new_getбудет вынужден породить следующую литеру как следующее возможное решение. Эта литера будет затем сравнена с 32 и так далее. В конце концов new_getнайдет неуправляющую литеру, сравнение закончится успешно и код этой литеры будет возвращен в качестве результата get.
Упражнение 6.1.Приведенное определение предиката getне будет работать надлежащим образом, если мы обратимся к целевому утверждению get(X)с уже определенным значением X. Почему это происходит?
Неприятность, связанная с предикатом repeat,состоит в том, что он всегда имеет альтернативное решение. Следовательно, в процессе возврата repeatникогда не будут пересмотрены решения, принятые раньше, чем произошел последний вызов repeat,если только мы не отсечем каким-либо образом эту постоянную возможность выбора. В силу сказанного предыдущие определения должны быть переписаны следующим образом:
new_get(X):- repeat, get0(X).
get(X):- new_get(X), X › 32,!.
Заметим, что это определение по-прежнему работает, лишь если мы пытаемся согласовать get(X)с неконкретизированной значением переменной X. Из-за проблемы, связанной с механизмом возврата за repeat,в каждом применении new_getнеобходимо предусматривать отсечение дальнейших вариантов, как только порождается литера, удовлетворяющая заданным условиям.
6.7. Формирование составных целевых утверждений
В правилах и вопросах вида X:-Yили ?-Yтерм, появляющийся на месте Y, может состоять из единственного целевого утверждения либо представлять конъюнкцию целевых утверждений или их дизъюнкцию. Более того, можно употреблять в качестве целевых утверждений переменныеи успешно доказывать согласованность целевого утверждения, когда целевое утверждение в действительности не согласуется, используя для этого предикат not.Предикаты, представленные в этом разделе, позволяют реализовать эти сложные способы выражения целевых утверждений.
Конъюнкция целей
Функтор ',' (запятая) определяет конъюнкцию целевых утверждений. Этот функтор был введен в гл. 1. Если Xи Y– целевые утверждения, то целевое утверждение X, Yсогласуется с базой данных, если согласуется Xи Y. Если Xсогласуется и затем Yне согласуется, то делается попытка найти новое доказательство согласованности для X. Если Xне согласуется, то не согласуется и конъюнкция в целом. Это и составляет суть механизма возврата. Функтор Yявляется встроенным и определен как левоассоциативный инфиксный оператор, так что X, Y, Zэквивалентно (X,Y),Z.
Дизъюнкция целей
Функтор ';' определяет дизъюнкцию (означающую или) целевых утверждений. Если Xи Y– целевые утверждения, то целевое утверждение X; Yсогласуется с базой данных, если согласуется Xили Y. Если Xне согласуется, то делается попытка доказать согласованность Y. Если и Yне согласуется, то не согласуется и дизъюнкция в целом. Мы можем использовать функтор ';' для того, чтобы выразить альтернативы в пределах одного утверждения. Например, будем считать, что некоторый объект является человеком, если этот объект – либо Адам либо Ева или если у объекта есть мать. Мы можем выразить это в одном правиле следующим образом:
человек(Х):- (Х=адам; Х = ева; мать(Х,Y)).
В этом правиле мы в действительности определили три альтернативы. Однако для Пролога это правило содержит две альтернативы, одна из которых сама содержит две альтернативы. Так как функтор ';' является встроенным и определен как правоассоциативный инфиксный оператор, то целевое утверждение в приведенном правиле в действительности можно переписать следующим образом:
';' (Х = адам, ';'(Х=ева,мать(Х, Y)))
Таким образом, первая возможность соответствует тому, что X– это адам. Вторая возможность включает две альтернативы: Xэто ева или у Xесть мать
Читать дальше