简体   繁体   中英

Simple append problems in Prolog

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM