我有一个如下的子句:
lock_open:- 条件组合(X), 等于(X,[8,6,5,3,6,9]),!, 打印(X)。
此子句成功。equal(X,[8,6,5,3,6,9])
但我想知道 conditional_combination() 在变为 true之前被调用了多少次。该程序是通过遵循一些规则来生成一个排列。我需要生成多少排列才能获得像 865369 这样的特定值。
您真正想要的是稍微不同的东西:您想要计算目标的答案数量(到目前为止)。
以下谓词call_nth(Goal_0, Nth)
成功,call(Goal_0)
但有一个附加参数,表明找到的答案是第 n 个答案。此定义高度特定于 SWI 或 YAP。不要在你的一般程序中使用类似的东西nb_setarg/3
,而是将它们用于封装良好的情况,就像这个一样。即使在这两个系统中,这些构造的确切含义也没有针对一般情况很好地定义。这是 SICStus 的定义。
call_nth(Goal_0, C) :- State = count(0,_), % 注意额外的参数,它仍然是一个变量 目标_0, arg(1,状态,C1), C2 是 C1+1, nb_setarg(1,状态,C2), C = C2。
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((1,5,I),Nth)。 我 = 第 N, 第 N = 1 ; 我 = 第 N,第 N = 2; 我 = 第 N,第 N = 3; 我=第N次,第N次= 4; 我 = 第 N 个,第 N 个 = 5。
所以简单地把它包起来:
lock_open :- call_nth(conditional_combination(X), Nth), X = [8,6,5,3,6,9], !, ……
如果您使用的是 SWI prolog,您可以使用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).
其他 prologs 有其他方法可以做同样的事情,在你的 prolog 实现中寻找全局变量。在此代码段中,我使用该术语ctr
来保存当前目标计数器。您可以使用程序中未使用的任何术语。
在开发“微型”模块时,我最近发明了枢轴。它们受到线程/管道模式的启发来传递数据。枢轴是最大长度为 1 的有界队列,pivot_put/1 也是给定术语的副本。但是出于性能原因,它们不使用同步并且是非阻塞的。
到目前为止,它们与 nb_setarg/3 非常相似,只是它们不破坏 Prolog 术语,而是更新 Java 数据结构。因此,它们比非逻辑项操作更安全一些。他们也不需要一些 call_cleanup/3,因为它们是 Java 垃圾收集的。
就目前而言,它们比 nb_setarg/3 更相似,而不是使用一些显式分配和释放结构。例如,SICStus Prolog 的解决方案可能是:
call_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.