过滤列表(Prolog)

时间:2015-09-09 20:20:04

标签: list filter prolog

我的目标是编写谓词SELECT start_time || start_date AS start_date_time FROM a_event; 。使用输入列表filter/3和过滤条件[bar(a,12),bar(b,12),bar(c,13)],预期输出为bar(A,12)

下面的代码有效但写[bar(a,12),bar(b,12)]\+ \+ Filter = X之间的区别是什么(对我而言,它是相同的)。我使用2个版本写下了程序,它给出了相同的正确结果。但我相信他们是不同的?!

Filter = X

修改  @lurker你是对的,他们没有给出相同的结果。 (这是我的错误)

----使用filter([],_,[]). filter([X|XS],Filter,[X|ZS]) :- \+ \+ Filter=X, !, filter(XS,Filter,ZS). filter([_|XS],Filter,ZS) :- filter(XS,Filter,ZS). -----

\+ \+ Filter = X

----使用?- filter([foo(a,12),foo(c,12),foo(b,13)],foo(A,12),Res). Res = [foo(a, 12), foo(c, 12)]. -----

Filter = X

2 个答案:

答案 0 :(得分:2)

双重否定它是一个旧的交易技巧'在编写元解释器时经常使用。

由于统一导致的变量实例化在回溯时无法实现,因此它具有过程唯一的语义&#34;证明一个目标而不绑定其变量&#34;,无论这个短语的含义是什么。< / p>

1 ?- filter([bar(a,12),bar(b,12),bar(c,13)],bar(_,12),L).
L = [bar(a, 12), bar(b, 12)].

如果您注释掉(即删除)双重否定,则会观察到过度的实例化效果:X已绑定到bar(a,12),然后无法与bar(b,12)匹配。< / p>

2 ?- filter([bar(a,12),bar(b,12),bar(c,13)],bar(_,12),L).
L = [bar(a, 12)].
对于手头的简单案例,

编辑,filter / 3的替代实现可能是

filter([],_,[]).
filter([X|XS],Filter,ZS):- 
    X \= Filter, !, filter(XS, Filter, ZS).
filter([X|XS],Filter,[X|ZS]):- 
    filter(XS, Filter, ZS).

或更好

filter([],_,[]).
filter([X|XS],Filter,R):- 
    (X \= Filter -> R = ZS ; R = [X|ZS]), filter(XS, Filter, ZS).

但是如果你的系统实现了subsumes_term / 2,那么@ Boris&#39;答案是首选

答案 1 :(得分:2)

answer by @CapelliC回答了您的问题。

还有另一个标准谓词subsumes_term/2,它可用于实现与双重否定相同的效果:

filter0([], _, []).
filter0([X|Xs], T, Ys) :-
    \+ subsumes_term(T, X),
    filter0(Xs, T, Ys).
filter0([X|Xs], T, [X|Ys]) :-
    subsumes_term(T, X),
    filter0(Xs, T, Ys).

至于如何对所有元素进行迭代,而不是剪切,更喜欢条件:

filter1([], _, []).
filter1([X|Xs], T, R) :-
    (   subsumes_term(T, X)
    ->  R = [X|Ys]
    ;   R = Ys
    ),
    filter1(Xs, T, Ys).

如果你写这个,你也可以使用include/3(顺便说一下,它实际上是一个“过滤器”谓词):

filter(List, Term, Filtered) :-
    include(subsumes_term(Term), List, Filtered).