Я хочу написать предикат, который повторяется до 0, но он постоянно не завершается. Я использовал срез отказов, чтобы сузить его до этого:
f(a, 0).
f(b, 0).
f(X, Y) :- false.
Когда я загружаю файл как swipl -f test.pl
, а затем запускаю f(X, 0).
в подсказке, я получаю вывод X = a
, но не вижу X = b
и не получаю новую подсказку. Я ожидаю, что он будет действовать как A is 1 + 1
, где я получаю A = 2.
с точкой и новой подсказкой ?-
.
Мне удалось заставить его работать с чем-то вроде этого, но это не кажется чистым:
f(X, 0) :- X = x.
f(X, Y) :- Y == 0 -> false; (NewY is Y - 1, f(X, NewY)).
Для списка я мог бы записать более общий случай как f(X, [A|B])
, чтобы гарантировать, что он применяется только тогда, когда в списке есть хотя бы один элемент. Могу ли я сделать что-то подобное, чтобы гарантировать, что более общий случай здесь применим только тогда, когда Y
не равен 0?
Я просмотрел этот вопрос, и хотя он намекает на правильное направление, это не тоже не работает:
:- use_module(library(clpfd)).
int_int_prod(_, 0, 0).
int_int_prod(Num1, Num2, Result) :-
Num2 #> 0,
NewNum2 #= Num2 - 1,
int_int_prod(Num1, NewNum2, NewResult),
Result #= Num1 + NewResult.
?- int_int_prod(0, 0, X).
X = x
, но он не останавливается. Мне удалось заставить его работать, поэтому я отредактирую то, что сделал. - person Andrew   schedule 07.07.2018f(x, 0).
, а ваш рекурсивный случай будетf(X, Y) :- Y > 0, Y1 is Y - 1, f(X, Y).
или лучше, поскольку вы рассуждаете о целых числах, используя CLP(FD):f(X, Y) :- Y #> 0, Y1 #= Y - 1, f(X, Y).
- person lurker   schedule 07.07.2018int_int_prod/3
? - person lurker   schedule 07.07.2018Y > 1
(илиY #> 0
) это аналогY = [ _ | _ ]
. - person Will Ness   schedule 07.07.2018X
с константойx
(обратите внимание на другой случай)? В таком случае лучше записать это как фактf(x, 0).
или хотя бы переименовать переменную для ясности. - person lambda.xy.x   schedule 08.07.2018int_int_prod
взято из связанного вопроса, я просто показывал свое исследование. - person Andrew   schedule 09.07.2018