你可能会逃避一个不使用append/3
的解决方案。例如,请考虑以下谓词,filter/3
:
filter(_Pattern, [], []).
filter(Pattern, [E|Es], Matches) :-
Pattern \= E, !,
filter(Pattern, Es, Matches).
filter(Pattern, [E|Es], [E|Matches]) :-
filter(Pattern, Es, Matches).
的filter/3
的第一条是基本情况,其中,如果有什么(左)在第二个参数列表相匹配,那么我们就得到一个空列表。由于我们没有考虑Pattern
,所以它被忽略(因此前面的_
针对变量)。
的filter/3
试验的第二条款,以查看是否Pattern
,这可能被绑定到一个术语(例如,foo(X,Y)
),可以统一与列表的E
第一元件相匹配。 \=
运算符将会成功时,它的参数不能统一,所以如果这个成功,当我们不匹配E
的模式,并可以扔掉它并继续(注意测试后切入!
提交到这个分支)。
的filter/3
最后(第三)子句是在第二子句依赖的,因为它只是简单地传递E
到假定它是的匹配Pattern
的最后一个参数列表Matches
,因为前述条款未能确定它是不是一场比赛。请注意,我们将E
附加到列表中,方法是将列表结构绑定到输出,使Matches
子列表解除绑定;完整的Matches
列表只有在达到基本情况后才会完全绑定,一旦我们用完第二个参数中的匹配条件,将其绑定到空列表[]
,创建类似[E1,E2,...,En|[]]
的匹配模式;每个E1
到En
匹配模式;这个词相当于名单[E1,E2,...,En]
。
测试这个谓词如下给出:
?- filter(foo(X,Y), [a,b,foo(x,y),c(f),foo(v(3),Z),5], L).
L = [foo(x, y), foo(v(3), Z)] ;
false.
注意,一切unifiable与图案foo(X,Y)
这里被过滤到必要L
。
最后一点:在你的代码中,append(foo(X,Y),R,L)
总是会失败,因为append/3
只对列表进行操作;您可能想拨打append([foo(X,Y)],R,L)
,但在这种情况下,您只需简单地使用L = [foo(X,Y)|R]
作为简写。
编辑:要匹配,你有可能的模式列表匹配和筛选您的特定情况下,这里是另一个谓语,filter_list/3
:
filter_list(_Patterns, [], []).
filter_list(Patterns, [E|Es], Matches) :-
filter(E, Patterns, []), !,
filter_list(Patterns, Es, Matches).
filter_list(Patterns, [E|Es], [E|Matches]) :-
filter_list(Patterns, Es, Matches).
注意filter_list/3
依赖于我以前的定义并且使用完全相同的策略实施:如果E
与Patterns
中的任何一个都不匹配(即,这是filter(E, Patterns, [])
成功的情况),那么我们忘记E
并继续,否则(最后一句)我们保留它。测试给了我们:
?- filter_list([foo(X,Y),bar(X),b], [a,b,foo(X,Y),c], L).
L = [b, foo(X, Y)] ;
false.