ответ Бориса идеален. Я просто хотел бы объяснить, почему ваша исходная программа и программа другого ответа не завершаются.
На первый взгляд вроде работает, в итоге получаем ответ:
?- countD(4,L).
L = [4, 3, 2, 1]
Но обратите внимание, что Пролог показал нам только первый ответ, есть еще, ждем...
?- countD(4,L).
L = [4, 3, 2, 1] ;
**LOOPS**
Лучший способ понять завершение в Прологе — это сосредоточиться на соответствующих частях вашей программы. Преимущество Пролога в том, что, хотя его фактический поток управления довольно сложен, часто бывает достаточно посмотреть на очень маленькую часть вашей программы, чтобы определить определенные свойства. Так что не надо "все сразу понимать".
Вместо того, чтобы смотреть на все подряд, я возьму следующий фрагмент отказа:
countD(0,[]) :- false.
countD(Num,List) :-
List = [Num|L],
countD(M,L), false,
Num is M+1.
В первой строке при вставке false
факт фактически удаляется. Таким образом, независимо от того, что именно он описывает, 0
или 1
не имеют никакого влияния на завершение этого предиката. В общем, незавершение любого среза отказа подразумевает не завершение исходной программы.
Конечно, мы должны найти правильный кусок. Это немного опыта. Но как только он найден, его свойства завершения легко проверить.
Чтобы решить эту проблему, мы можем сразу сказать, что добавление дополнительного предложения не улучшит завершение (при условии, что программа чистая, монотонная). Нам нужно что-то изменить в видимой части. Борис сделал это, добавив некоторую проверку для Num
перед фактической рекурсией.
person
false
schedule
01.12.2014