Prolog 芬德尔的替代品

Prolog 芬德尔的替代品,prolog,prolog-findall,Prolog,Prolog Findall,我正在尝试在Prolog中创建一个替代findall 我得到的是: solutions(A,T,S) :- T, assert(temp(A)), fail. solutions(A,T,S) :- obtain([],S). obtain(X,S) :- retract(temp(A)), obtain([A|X],S). obtain(S,S). 然而,这给了我不一致的结果。怎么了?提前感谢您。您的实现存在几个问题 开始时没有清理。在T之前添加ret

我正在尝试在Prolog中创建一个替代
findall

我得到的是:

solutions(A,T,S) :- 
   T,
   assert(temp(A)),
   fail.
solutions(A,T,S) :-
   obtain([],S).

obtain(X,S) :-
   retract(temp(A)),
   obtain([A|X],S).
obtain(S,S).

然而,这给了我不一致的结果。怎么了?提前感谢您。

您的实现存在几个问题

  • 开始时没有清理。在
    T之前添加
    retractall(温度())

  • acquire/2
    将获得许多不同的答案,因为
    retract(temp(A))
    将给出许多答案,并且因为第二个子句
    acquire(S,S)
    将始终是一个解决方案。这可以通过在
    retract
    |?-获取([],S)后添加切口来保存。 | ?- obtain([],S). S = [2,1] ? ; S = [1] ? ; S = [2] ? ; S = [] ? ; no S=[2,1]; S=[1]; S=[2]; S=[]; 不

  • 您可能希望通过使用
    asserta/1
    或重新定义
    get/2
    来更改顺序

  • 您的定义不是重新进入。这是不容易解决的。您可能需要一些类似gensym的功能或更高级的功能

  • 有关
    assert/1
    assertz/1
    的详细信息,请参阅

  • 尝试此操作,在retract/1后使用一个切口(!)并显式assertz/1:

    solutions(A,T,_) :- 
       T,
       assertz(temp(A)),
       fail.
    solutions(_,_,S) :-
       obtain(S).
    
    obtain([A|S]) :-
       retract(temp(A)), !,
       obtain(S).
    obtain([]).
    
    工作正常,但不可重入,第二个查询结果错误:

    ?- solutions(X,between(1,3,X),L).
    L = [1, 2, 3].
    
    ?- solutions(X-R,(between(1,3,X),solutions(Y,between(1,X,Y),R)),L).
    L = [3-[2-[1-[1], 1, 2], 1, 2, 3]].
    
    编辑2020年11月8日:
    下面是使用gensym/2的可重入解决方案:

    solutions(A,T,L) :-
       setup_call_cleanup(
          gensym('bag',B),
          solutions(B,A,T,L),
          retractall(temp(B,_))).
    
    solutions(B,A,T,_) :- 
       T,
       assertz(temp(B,A)),
       fail.
    solutions(B,_,_,S) :-
       obtain(B,S).
    
    obtain(B,[A|S]) :-
       retract(temp(B,A)), !,
       obtain(B,S).
    obtain(_,[]).
    
    现在两个查询都可以正常工作:

    ?- solutions(X,between(1,3,X),L).
    L = [1, 2, 3].
    
    ?- solutions(X-R,(between(1,3,X),solutions(Y,between(1,X,Y),R)),L).
    L = [1-[1], 2-[1, 2], 3-[1, 2, 3]].
    
    警告:具有逻辑更新语义的Prolog系统

    重复收回/1时可能无效。

    您能描述一下结果中的不一致之处吗?也许使用
    assertz
    而不是
    assert
    可以解决这个神秘的不一致性。@EugeneSh。我相信,
    assert
    assertz
    做同样的事情。:)@“潜伏者”会断言“保证”附加到结尾吗?我找不到任何提到它的东西。@EugeneSh。如果它是SWI Prolog,那么我相信它是从那时起。我不知道为什么会不一致。我仍在等待OP解释什么是不一致的。:)