I've been studying Prolog for a few weeks ago and something trivial I keep getting stuck on is coming up with solutions using append.
For example, if I have a pattern matching rule that looks something like
pattern( foo(X,Y), L1, L ) :-
% some code to go through a list (where the foo-pattern is)
% and add the pattern to the list L if it matches`
I know that append/3 is the way to go here but.. L starts of unknown ie not ground and as we start recursion the list it starts filling up with the matched patterns. However, I always get confused with what initially happens ie when L is not ground.
For example, here's a broken bit of code where we want to get a list of all the matched patterns when the first parameter is a list of possible patterns:
pat([foo(X,Y)|L1], R, L) :-
append(foo(X,Y),R,L),
pat(L1, R, [D|L]).
pat([_|L1], R, L2) :-
pat(L1, R, L2).
Many thanks.
You can probably get away with a solution that doesn't use append/3
. For example, consider the following predicate, 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).
The first clause of filter/3
is the base case, where if there is nothing (left) to match in the 2nd argument list, then we get an empty list. Since we didn't consider the Pattern
, it is ignored (hence the preceding _
against the variable).
The second clause of filter/3
tests to see if Pattern
, which could be bound to a term (eg, foo(X,Y)
), can unify with the first element of the list to match, E
. The \\=
operator will succeed when it's arguments cannot be unified , so if this succeeds, when we didn't match E
to the pattern, and can throw it away and continue (note the cut !
after the test to commit to this branch).
The last (third) clause of filter/3
is reliant on the second clause, because it simply passes E
onto the last argument list Matches
assuming that it is a match to Pattern
, because the preceding clause failed to determine that it wasn't a match. Note that we are appending E
to the list by binding a list structure to the output leaving the Matches
sublist unbound; the full Matches
list will only be fully bound once it reaches the base case, binding it to the empty list []
once we run out of terms to match in the 2nd argument, creating something like [E1,E2,...,En|[]]
, where every E1
to En
matched the pattern; this term is equivalent to the list [E1,E2,...,En]
.
Testing this predicate as follows gives:
?- 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.
Note that everything unifiable with the pattern foo(X,Y)
here was filtered out into L
as necessary.
One final note: In your code, the call append(foo(X,Y),R,L)
will always fail, because append/3
operates on lists only; you probably wanted to call append([foo(X,Y)],R,L)
instead, but in that case, you an simply use L = [foo(X,Y)|R]
as a shorthand instead.
EDIT: To match your particular case where you have a list of possible patterns to match and filter on, here is another predicate, 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).
Note that filter_list/3
depends on my previous definition of filter/3
, and is implemented using exactly the same strategy: if E
doesn't match any of the Patterns
(ie, this is the case where filter(E, Patterns, [])
succeeds), then we forget E
and continue, else (last clause) we keep it. Testing gives us:
?- filter_list([foo(X,Y),bar(X),b], [a,b,foo(X,Y),c], L).
L = [b, foo(X, Y)] ;
false.
我不需要在您的示例代码中看起来像父亲... append(foo(...标准的append / 3谓词在列表上进行操作。append(foo(Anything),...将不匹配其子句中的任何一个)因此,您的第一个example子句应该总是失败,而第二个example子句应该失败,或者开始构建无限数量的未绑定变量,最终在内存用尽时被炸毁。至于您最终想要在这里做什么,目前尚不清楚我,但听起来您不想像模式匹配那么多,而不必在列表中查找与给定术语统一的项目,为什么您认为append / 3是可行的方式?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.