r1(X,Z) :- backwards(X,Z).
r1_10(X,Z) :-
r1(X,Z),
我有这个代码。想法是如果r1满足10次则满足r1_10。我是Prolog的新手,我不知道如何正确地循环这个。我正在考虑只是粗暴强迫同一行10次,但我需要能够做像r1_30这样的事情,所以这将是很多代码无缘无故。
谢谢!
编辑: 这个答案帮了很多忙,但只是为了澄清我在问什么。基本上,我的目标r1调用我的向后/ 2谓词,它只是让我反向列表。我有两种类型的向后/ 2谓词,一种包括累加器而另一种不包含累加器。 r1_10只是一个目标,最终会告诉我使用累加器的那个更快更好。目标r1_10只是将目标r1运行10次的一种方式。我很确定我不需要不同的结果,我只需要能够知道当r1完成10次后它会成功。希望这有帮助!
答案 0 :(得分:2)
目前尚不清楚“满意10次”是什么意思。你的意思是r1/2
谓词有10个解决方案吗?一个例子是目标member(X, [1,2,3,4,5,6,7,8,9,0])
,它在回溯时会连续地将变量X
实例化到每个列表元素。如果是这样,一个解决方案可能是使用标准findall/3
谓词来计算目标的所有解决方案的列表,然后计算列表的长度。例如:
r1_10(X,Z) :-
findall(_, r1(X,Z), Solutions),
length(Solutions, 10).
通过使用附加参数传递要检查的解决方案的数量,可以很容易地推广此谓词。它也可以通过使用另一个参数来推广目标本身来推广。
另一方面,如果你想简单地调用一次目标N次,你可以定义一个带有目标和计数器的谓词。例如:
call_n_times(N, Goal) :-
between(1, N, _), % generate, on backtracking, all numbers in the interval [1,N]
once(Goal),
fail.
call_n_times(_, _).
然而,这个定义假设目标永远不会失败(或抛出错误)。从你的问题不清楚如果目标不能满足N次会发生什么。在这种情况下呼叫者应该失败吗?如果是这样,您将需要不同的定义。例如(假设目标永远不会失败或抛出错误):
call_n_times(0, _) :- !. % green cut just to avoid a spurious choice-point
call_n_times(N, Goal) :-
N > 0,
once(Goal),
M is N - 1,
call_n_times(M, Goal).
但这个定义仍然存在问题。例如,如果你传递一个非基础的目标,即其中包含变量,并且调用目标会以防止其在下一步中成功的方式实例化其中的一些变量。避免这个潜在问题的一种方法是使用以下紧凑定义:
call_n_times(N, Goal) :-
forall(between(1,N,_), Goal).
forall/2
和between/3
是事实上的标准谓词。当第一个参数的每个解决方案都是第二个参数为真时(因此实现了生成和测试循环),forall/2
谓词为真。
我们可以使用您想要完成的更多细节,包括您想要重复的目标的性质。