我的目标是编写谓词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
答案 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).