Программирование на языке пролог
Шрифт:
устконтрточку(Заголовок, Тело),
отказ(3аголовок, Тело),
write('контр.точка с терма'), печтерм(Функтор, ЧисАрг),
write(' удалена.'),nl,
fail
; true
)
; write('Heт контр.точек на терме'),
write(X), put(46), nl
),
!.
гораздо труднее для понимания, нежели:
nospy(X):-проверить(Х,Функтор,ЧисАрг,А),!,
попыт_убр(Х,Функтор,ЧисАрг,А).
попыт_убр(_,Функтор, ЧисАрг,А):- контрточка(_,Функтор,А),!,убрконтрточку(Функтор, ЧисАрг, А).
попыт_убр(Х,_,_,_):- write('Heт контр.точек на терме '), write(X), put(46), nl,!.
убрконтрточку(Функтор, ЧисАрг, А):-
write('Koнтp.точка с терма'), печтерм(Функтор, ЧисАрг), write(' удалена.'), nl, fail.
убрконтрточку (_,_,_).
которая делает в точности то же самое. Если же вам действительно необходимо использовать «или», то полезно так организовать текст конъюнкции целей, чтобы «или» не терялось среди целей. Полезно также заключить соответствующие цели в скобки, чтобы явно выделить область действия этого «или».
На протяжении всей книги подчеркивалась важность умения учитывать при решении многих задач наряду с общим правилом и граничные условия. Всюду, где это возможно, мы старались разместить граничные условия перед всеми другими утверждениями процедуры. Это выделяет граничные условия и, кроме того, служит в какой-то мере защитой от циклических определений. Однако бывают случаи, когда желательно размещать граничные условия после всех утверждений процедуры. Очевидно, что правила-«ловушки», с которыми мы уже сталкивались несколько раз, нужно размещать в конце процедуры.
Разбирая Пролог-процедуру всегдаполезно обращать внимание на следующие важнейшие моменты ее записи:
• Проверьте посимвольно,как записано имя каждого предиката и каждой переменной в процедуре. Ошибки в написании имен довольно распространены.
• Проверьте число аргументовкаждого функтора, используемого в процедуре. Убедитесь в том, что число аргументов (и порядок их следования) соответствуют вашим проектным решениям.
• Выделите из утверждений все операторыи определите их приоритет, ассоциативность, а также то, где находятся их аргументы. Это можно сделать на основании определений операторов, и исходя из наличия скобок. Если есть сомнения, добавьте дополнительные скобки. Для проверки соответствия действия оператора вашим представлениям попробуйте распечатать некоторые простые термы, используя display.
• Обратите внимание на область определениякаждой переменной и выделите в этой области переменные, сходные с ней по имени. Проследите, какие переменные «сцепляются», когда одной из них будет присвоено значение. Проверьте, встречаются ли в теле утверждения переменные из его заголовка.
• Постарайтесь определить, какие переменные конкретизированы, а какие нет в момент перед применением утверждения.
• Выделите утверждения, составляющие граничные условия. Проверьте, учтены ли все возможные граничные условия.
После того как подобным образом процедура будет разобрана «по косточкам», вы поймете ее гораздо лучше.
8.2. Типичные ошибки
В этом разделе мы рассмотрим те ошибки, которые допускают как начинающие, так и опытные программисты, использующие Пролог. Эти ошибки делятся на две группы: синтаксическиеошибки и ошибки управления последовательностьюобработки.
После того, как программист решил, какую программу он будет писать и как разместит ее текст на странице
печатающего устройства (или на экране видеотерминала), ему остается ввести текст программы, записав его в файл или непосредственно в базу данных Пролог-системы. Основная задача данного этапа – это обеспечить синтаксическуюправильность программы. Ниже приводится список типичных синтаксических ошибок. Если программист сам не выявит эти ошибки, то при попытке выполнить предикат consultПролог может выдать соответствующее сообщение.• Одной из типичных синтаксических ошибок является отсутствие точки '.' в конце утверждения. Точкой должен заканчиваться и любой терм, считываемый с помощью предиката read. После точки нужно оставлять хотя бы один пробел. Поэтому избегайте заканчивать файл вместе с вводом точки последнего утверждения – убедитесь в том, что в самом конце вы не забыли нажать клавишу
• Некоторые специальные литеры используются парами. К ним относятся круглые скобки '(' и ')', используемые для группирования термов, квадратные скобки '[' и ']', используемые для задания списков, и фигурные скобки '{' и '}', используемые для записи правил грамматики (см. гл. 9). Сюда же относятся двойные кавычки '"' используемые для ограничения строк и одиночная кавычка '", используемая для задания атомов. Составные скобки '/*' и '*/' используются для ограничения комментариев. Убедитесь, что скобок каждого вида задано не больше и не меньше чем необходимо.
• Остерегайтесь неправильного написания слов, особенно имен встроенных предикатов. Это может привести к самым неожиданным ошибкам, поскольку неверно записанные имена предикатов вряд ли сопоставятся с каким-либо утверждением в базе данных. Или наоборот, они могут неожиданно сопоставиться с утверждениями, заголовок которых случайно совпадает с получившимся именем.
• Еще одним источником возможных ошибок являются операторы. Когда вы не уверены в ассоциативных свойствах оператора, то используйте круглые скобки, чтобы задать нужные свойства явно. Проверяйте экспериментально действие введенных вами операторов с помощью предиката display.
• Когда имеете дело с операциями над списками, проверяйте себя с помощью следующих вопросов и ответов:
• Как сопоставляются [а,b,с]и [X|Y]? ( X конкретизируется значением a, a Y– значением [b,с]).
• Сопоставимы ли [а]и [X|Y]? (Да, причем X конкретизируется значением a, a Y– значением []).
• Сопоставимы ли []и [X|Y]? (Нет).
• Имеет ли смысл запись [X, Y|Z]? (Да).
• Имеет ли смысл запись [X|Y,Z]? (Нет).
• Имеет ли смысл запись [Х|[Y|Z]? (Да, это то же самое, что [X,Y|Z])
• Как сопоставляются [a, b]и [А |В]? ( А конкретизируется значением а, а В– значением [b] ).