Программирование на языке Пролог | страница 78




присоединить([а,b,с],[d,е],Х)


и


присоединить([а,b,с],Х,Y)


то использование отсечения вполне уместно. Если первый аргумент такого целевого утверждения уже имеет некоторое значение, то единственный смысл отсечения – это подтверждение того, что когда значение первого аргумента есть [], то только первое правило применимо. Однако рассмотрим, что произойдет, если мы имеем целевое утверждение


присоединить(Х,Y,[а,b,с]).


Это целевое утверждение будет сопоставлено с заголовком первого правила, что даст

X = [], Y = [a,b,c]

но затем встретится отсечение. Это приведет к тому, что будет заморожен сделанный нами выбор правила, и как следствие в случае если мы обратимся за новым решением, ответ будет «нет», даже если в действительности для данного запроса имеются другие решения.

Приведем другой интересный пример того, что может произойти, если правило, содержащее отсечение, используется незапланированным способом. Давайте определим предикат число_родителей, который дает информацию о том, сколько родителей имеет человек. Мы можем определить его следующим образом:


число_родителей(адам,0):-!.

число_родителей(ева,0) :-!.

число_родителей(Х,2).


то есть число родителей для адам и ева равно 0, а для всех остальных равно 2. Если мы всегда используем наше определение предиката число_родителей для определения числа родителей некоторого данного человека, то все идет нормально. Мы получаем


?- число_родителей(ева,Х).

X = 0; нет

?- число_родителей(джон,Х).

X = 2;

нет


и так далее, как это и требуется. Отсечение необходимо, чтобы предотвратить процесс возврата, который мог бы привести к третьему правилу в случае, когда человек – это адам или ева. Однако рассмотрим, что произойдет, если мы используем те же самые правила, чтобы проверить, что данный человек имеет данное число родителей. Все хорошо, за исключением того, что мы получаем


?- число_родителей(ева,2).

да


Вам следует самостоятельно разобраться, почему так получается – это просто следствие стратегии, применяемой в Прологе для поиска в базе данных. Наша реализация обработки «остальных» случаев, основанная на использовании отсечения, просто больше не работает надлежащим образом. Существуют два способа изменить определение, которые позволили бы нам устранить указанный эффект:


число_родителей(адам,N):-!, N=0.

число_родителей(ева,N):-!, N=0.

число_родителей(Х,2).


или


число_родителей(адам,0).

число_родителей(ева,0).

число_родителей(Х,2):- X \= адам, X \= ева.


Конечно, эти определения по-прежнему не работают, если задать целевое утверждение вида