我希望有一个简单的函数,它可以获取一种类型的所有事实并列出它:
% Facts
fact('a','1').
fact('b','2').
fact('c','3').
% Call
all_facts(L) :- ......
% Expected
27 ?- all_facts(L).
L = [ ('a', '1'), ('b', '2'), ('c', '3')].
我知道forall / 3已经很好了,可能是任何现实场景中的首选用法:
all_facts(L) :- findall(
(LETTER, NUMBER),
fact(LETTER, NUMBER),
L
).
但我并没有尝试在此处实现此功能。我想要理解它背后的逻辑,因为我对Prolog来说相对较新。到目前为止,我在这里:
all_facts([(LETTER, NUMBER)|Rest]) :- fact(LETTER, NUMBER), fail.
这会按顺序通过所有事实,因为它会一直失败。我的问题是将它们实际保存在列表中。
答案 0 :(得分:3)
正如@mat在Prolog的书中提出的那样你可以写:
all_facts( Template, Enumerator, List ) :-
asserta( 'find all'( [] ) ),
call( Enumerator ),
asserta( 'find all'( {Template} ) ),
fail
;
'all found'( [], List ).
'all found'( SoFar, List ) :-
retract( 'find all'( Item ) ),!,
'all found'( Item, SoFar, List ).
'all found'( [], List, List ).
'all found'( {Template}, SoFar, List ) :-
'all found'( [Template|SoFar], List ).
示例:
?- all_facts((X,Y),fact(X,Y),L).
L = [ (a, '1'), (b, '2'), (c, '3')].
这背后的基本思想是静态地(从事实/ 2)断言从文件加载的术语,但是动态地(使用断言)以便能够在使用它们时收回它们。