требует особого внимания, поскольку мы обычно не считаем мир замкнутым: если в программе явно не сказано, что
человек( мэри)
то мы этим обычно вовсе не хотим сказать, что Мэри не человек.
Дальнейшее изучение опасных аспектов использования not
проведем на таком примере:
r( а).
g( b).
p( X) :- not r( X).
Если спросить теперь
?- g( X), p( X).
система ответит
X = b
Если же задать тот же вопрос, но в такой форме
?- p( X), g( X).
система ответит
nо
(нет)
Читателю предлагается проследить работу программы по шагам, чтобы понять, почему получились разные ответы. Основная разница между вопросами состоит в том, что переменная X к моменту вычисления p( X)
в первом случае была уже конкретизирована, в то время как во втором случае этого еще не произошло.
Мы детально обсудили аспекты применения отсечения, которое неявно присутствует в not
. При этом нами руководило желание предупредить пользователей о соблюдении необходимой осторожности, а вовсе не желание убедить их совсем не пользоваться этим оператором. Отсечение полезно, а часто и необходимо. А что касается трудностей Пролога, порождаемых отсечением, то подобные неудобства часто возникают и при программировании на других языках.
Резюме
• Отсечение подавляет перебор. Его применяют как для повышения эффективности программ, так и для повышения выразительности языка.
• Эффективность повышается путем прямого указания (при помощи отсечения) пролог — системе не проверять альтернативы, про которые нам заранее известно, что они должны потерпеть неудачу.
• Отсечение дает возможность сформулировать взаимно исключающие утверждения при помощи правил вида:
• Отсечение дает возможность ввести not( Цель)
определяется через неуспех цели Цель
.
• Иногда бывают полезными две особые цели true
и fail
. true
— всегда успешна и fail
— всегда терпит неудачу.
• Существуют ограничения в применении отсечения: его появление может нарушить, соответствие между декларативным и процедурным смыслами программы. Поэтому хороший стиль программирования предполагает осторожное применение отсечений и отказ от их применения без достаточных оснований.
• Оператор not
, определенный через неуспех, не полностью соответствует отрицанию в математической логике. Поэтому not
тоже нужно применять с осторожностью.
Различать 'зеленые и 'красные' отсечения предложил ван Эмден (1982).
van Emden M. (1982). Red and green cuts.
Глава 6
Ввод и вывод
В этой главе мы рассмотрим некоторые встроенные средства для записи данных в файл и считывания их из файла. Такие средства можно также применять и для форматирования объектов данных программы, чтобы получить желаемую форму их внешнего представления. Одновременно мы рассмотрим и средства синтеза и декомпозиции атомов.
6.1. Связь с файлами
До сих пор мы применяли только один метод связи пользователя с программой — пользователь задает программе вопросы, а программа ему отвечает, конкретизируя переменные. Такой механизм связи прост и практичен и, несмотря на свою простоту, обеспечивает ввод и вывод информации. Однако он обладает слишком малой гибкостью и поэтому часто не совсем удобен. В следующих случаях требуется расширение этого основного механизма связи:
• ввод данных в форме, отличной от вопроса - например, в виде предложений, написанных на английском языке
• вывод информации в произвольном формате
• обмен информацией с произвольным файлом, а не только с пользовательским терминалом
Встроенные предикаты, предназначенные для этого расширения, отличаются в разных реализациях Пролога. Мы изучим здесь простой и удобный набор таких предикатов, применяемый во многих реализациях. Однако за деталями и специфическими особенностями следует, конечно, обращаться к руководствам по конкретным пролог-системам.
Рис. 6. 1. Связь между пролог-программой и различными файлами.
Рассмотрим вначале вопрос о том, как обмениваться информацией с файлами, а затем — как можно вводить и выводить данные в разных форматах.
На рис. 6.1 показана общая ситуация, в которой пролог-программа взаимодействует с несколькими файлами. Она может, в принципе, считывать данные из нескольких входных файлов, называемых также user
(пользователь). Имена остальных файлов программист должен выбирать в соответствии с правилами именования файлов, принятыми в используемой компьютерной системе.
В каждый момент выполнения пролог-программы лишь два файла являются 'активными': один для ввода, другой — для вывода. Эти два файла называются