高阶谓词:将一个列表分成两个列表,一个满足谓词,另一个不满足谓词



我试图创建一个谓词,它得到一个列表和一个谓词。满足给定谓词的给定列表中的每个元素都应该进入列表1,否则应该进入列表2。

例如:

partition(>(6), [1,7,5,6,3,8], Rs1, Rs2)

的结果应该是Rs1=[1,5,3]和Rs2=[7,6,8]

我试过了:

partition(P, [], [], []).
partition(P, [X|Xs], Rs1, Rs2) :- 
call(P,X,T),
((T=true, append(Rs1, X, Rs12))
; (T=false, append(Rs2, X, Rs22))),
partition(P, Xs, Rs12, Rs22).

但是由于某种原因我没有得到想要的结果。为什么?

我会这样做:

test(X) :- X > 5 .
partition( []     , _ ,    []  ,    []  ) .
partition( [X|Xs] , G , [X|Ys] ,    Zs  ) :- call(G,X), !, partition(Xs,G,Ys,Zs) .
partition( [X|Xs] , G ,    Ys  , [X|Zs] ) :-               partition(Xs,G,Ys,Zs) .

partition/3分解为单独的子句,每个子句处理一个特定的情况,简化了您的代码,使其更容易理解。

也不需要使用append/3。这可以在谓词的头部完成。这使得你的代码(1)更高效,(2)更容易理解。

移动源列表,使其成为第一个参数,也允许Prolog索引它(另一个性能提升,假设它在调用时被绑定)。