你可能會逃避一個不使用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.