可以在知识库中保留动态计数器类谓词,每次执行主谓词时都会增加该谓词。计数器的值更改为
assert
和
retract
也就是说,它不是主谓词中的变量,而是全局存储的值。
在主谓词中,如果添加了计数器应高于某个跳过值的条件,则强制对指定迭代次数的实际规则进行回溯。
例如,考虑内置谓词
permutation/2
它计算列表的排列(注意:使用swi prolog测试,其他解释器有不同的内置谓词)。示例输出:
?- permutation([1,2,3,4,5],L).
L = [1, 2, 3, 4, 5] ;
L = [1, 2, 3, 5, 4] ;
L = [1, 2, 4, 3, 5] ;
L = [1, 2, 4, 5, 3] ;
L = [1, 2, 5, 3, 4] ;
L = [1, 2, 5, 4, 3] ;
如果希望跳过查询中的前5个迭代,可以使用以下代码:
:- dynamic iteration_nr/1.
iteration_nr(0).
get_permutations(L1,L2,Skip) :-
permutation(L1,L2),
iteration_nr(N),
N2 is N+1,
retract(iteration_nr(N)),
asserta(iteration_nr(N2)),
Skip < N2. % force backtracking here if counter < Skip
示例输出:
?- get_permutations([1,2,3,4,5],L2,5).
L2 = [1, 2, 5, 4, 3] ;
L2 = [1, 3, 2, 4, 5] ;
L2 = [1, 3, 2, 5, 4]
注意
asserta
在这里使用(即,在开始时断言)而不是普通的
断言
,已弃用。还要注意,计数器将保留该值,因此在同一会话中再次运行该值时,结果将不同。若要重置计数器,可以使用单独的初始化谓词,例如:
init_and_get_permutations(L1,L2,Skip) :-
retractall(iteration_nr(_)),
asserta(iteration_nr(0)),
get_permutations(L1,L2,Skip).
进一步说明:使用
断言
和
收回
并不是真正意义上的“干净”prolog编程,因为它是过程性的,改变了知识库。然而,对于某些应用,它可能是有用的。