我有一个像下面这样的子句:
lock_open:- conditional_combination(X), equal(X,[8,6,5,3,6,9]),!, print(X).
这个子句会成功执行。但是我想知道在equal(X,[8,6,5,3,6,9])
变为真之前,conditional_combination()
被调用了多少次。程序根据一些规则生成排列,我需要知道生成特定值(如865369)所需的排列数量。
call_nth(Goal_0, Nth)
的成功与 call(Goal_0)
类似,但有一个额外的参数,指示找到的答案是第n个答案。该定义高度特定于SWI或YAP。在一般程序中不要使用像nb_setarg/3
这样的东西,而是将其用于封装良好的情况,如此例。即使在这两个系统中,这些构造的精确含义对于一般情况也没有很好地定义。这里是SICStus的定义。更新:在较新版本中使用unsigned_64
而不是unsigned_32
。一个更加健壮的抽象由Eclipse提供:
call_nth(Goal_0, Nth) :-
shelf_create(counter(0), CounterRef),
call(Goal_0),
shelf_inc(CounterRef, 1),
shelf_get(CounterRef, 1, Nth).
?- call_nth(between(1,5,I),Nth). I = Nth, Nth = 1 ; I = Nth, Nth = 2 ; I = Nth, Nth = 3 ; I = Nth, Nth = 4 ; I = Nth, Nth = 5.
所以只需要简单地包装一下:
lock_open :- call_nth(conditional_combination(X), Nth), X = [8,6,5,3,6,9], !, ....
nb_getval/2
和nb_setval/2
来达到你想要的效果:lock_open:-
nb_setval(ctr, 0), % Initialize counter
conditional_combination(X),
nb_inc(ctr), % Increment Counter
equal(X,[8,6,5,3,6,9]),
% Here you can access counter value with nb_getval(ctr, Value)
!,
print(X).
nb_inc(Key):-
nb_getval(Key, Old),
succ(Old, New),
nb_setval(Key, New).
其他的Prolog实现有其他的方法来完成同样的任务,在您的Prolog实现中查找全局变量。在这个片段中,我使用术语ctr
来保存当前目标计数器。您可以使用任何在程序中未使用的术语。
conditional_combination/1
中调用 nb_setval/2
将会影响结果。像 ctr
这样的名称可能会被用于其他计数... - falsefindall/3
使用asserta/retract为例。您不能嵌套此类调用,也不能同时进行两个调用。 - falsecall_nth(Goal_0, Nth) :-
new(unsigned_32, Counter),
call_cleanup(call_nth1(Goal_0, Counter, Nth),
dispose(Counter)).
call_nth1(Goal_0, Counter, Nth) :-
call(Goal_0),
get_contents(Counter, contents, Count0),
Count1 is Count0+1,
put_contents(Counter, contents, Count1),
Nth = Count1.
有了枢轴,甚至没有32位的限制,我们可以直接进行:
call_nth(G, C) :-
pivot_new(P),
pivot_put(P, 0),
call(G),
pivot_take(P, M),
N is M+1,
pivot_put(P, N),
C = N.
call_nth/2
清单的第三行)。我以为总是需要call(Goal)
,但显然,只有Goal
就足够了! - user1812457