Вы можете попытаться пройти через свою программу шаг за шагом, чтобы понять, что происходит. Вы будете очень медленными и очень ненадежными. Или, вместо этого, Prolog делает (часть) работу. Поэтому идея состоит в том, чтобы немного изменить программу, а затем посмотреть, что пролог думает об этом.
Это то, что я вижу, когда я смотрю на вашу программу - это называется failure-slice
fact(0,1) :- false.
fact(N,F) :-
fact(N1,F1), false,
N is N1 + 1,
F is N * F1.
Когда этот фрагмент прекращается? Посмотрите на оставшуюся видимую часть! N
встречается только один раз в голове: никто не интересуется первым аргументом! То же самое для F
. Поэтому: Независимо от того, какие аргументы у вас есть, программа не будет завершена. И, таким образом, то же самое относится к вашей оригинальной программе!
В оригинальной версии это было не так ясно. Берегитесь:
?- fact(29,F).
F = 8841761993739701954543616000000
На первый взгляд это выглядит красиво, но если вы спросите на следующий ответ (с пробелами или ;
), вы закончите в цикле. Хуже того, ложные запросы в настоящее время цикл сразу:
?- fact(29,1).
** LOOPS **
Итак, как вы можете найти эти проблемы, не понимая, что именно происходит? Это то, что false
для. Цель, которая никогда не верна. Если вы добавите его как fact(29,F), false.
, вы никогда не будете отвлекаться на красивые ответы.
Почему вы положили всю свою арифметику в конце? Я подозреваю, что раньше у вас были некоторые ошибки. Существует простой способ, чтобы избежать всех этих ошибок:
:- use_module(library(clpfd)).
Вы пишете вместо is
Теперь #=
, и вам необходимо некоторое ограничение, как N #>= 1
. Могу ли я оставить вас там?
Вы также можете вручную «пройти» через него: 'fact (3, F)' не соответствует 'fact (0, 1)' (поскольку 3 и 0 не являются унифицируемыми), поэтому Prolog будет соответствовать следующему пункту 'fact (N, F)' с 'N = 3'. Затем он вызывает «факт (N1, F1)», который снова появляется с «N1 = 0» и «F1 = 1» для первого предложения, и так далее. Обратите внимание: после нахождения решения он пытается найти больше и не заканчивается, вызывая переполнение стека. – lurker
Мне любопытно: как вы начали писать этот предикат, если не знаете, как это работает? – lurker
@lurker: Это очень понятно: другая версия, возможно, вызвала ошибку создания. – false