tags:

views:

526

answers:

2

I'm just starting with Prolog, and I can't figure out why the the following doesn't work as I expect it to. I'm trying to create a predicate that returns true if list L2 is contained in L1. This is what I wrote:

assert(contains (L1, L1)).
assert(contains(L1, [X|L2]):-member(X, L1), contains(L1, L2)).
assert(contains(L1, [])).

I figured this will be the equivalent of "if X of 'L3=X|L2' is in L1, and also L2 is in L1 then true", with contains(L1, L2) being translated recursively until either all members have been traversed and we are left with the last option, or we find a member that is not in L1, and it will fail the predicate.

Unfortunately it doesn't seem to work that way. It seems to only return the value of member(X, L1), so contains([1,2,3],[1,4,5]) passes, but contains([1,2,3],[4,1,5]) doesn't.

What am i doing wrong?

+2  A: 

I didn't completely understand your question but I would write the contains/2 predicate like this:

% An empty list is contained by any list
contains(_, []).

% If a list is not empty, then its
% first element must be an element of L1,
% and its tail must be contained by L1.
contains(L1, [X | L2]) :-
    member(X, L1),
    contains(L1, L2).

Btw, note that your first rule (fact)

contains (L1, L1).

is a syntax error (there shouldn't be a space after the predicate name). Also, if corrected, it would create an unwanted choicepoint. So, rather delete it.

In case you want to use assert/1 on the Prolog prompt, then execute

?- assert(contains(_, [])).

Yes
?- assert(contains(L1, [X | L2]) :- (member(X, L1), contains(L1, L2))).

Yes

To see what ended up in the knowledge base, use listing/0.

?- listing.

:- dynamic contains/2.

contains(_, []).
contains(B, [A|C]) :-
    member(A, B),
    contains(B, C).

Yes

I don't think the problem is with "asserting free variables" as you indicate in your own answer. Rather, check your bracketing.

Kaarel
I tried what you asked, and it has the same problem: if I invoke contains([1,2,3],[1,2,4]), it replies with "yes"
Epsilon Vector
Strange, in my case it replies "false."
Kaarel
A: 

Apparently using asserts on free variables can cause problems (at least in this version), so that's why it misbehaved. Dropping the asserts and using a consult(file) command solved this.

Epsilon Vector
Your original question says nothing about assert. What exactly did you assert?
Kaarel
I basically wrote it in the prompt so I asserted everything. Added the asserts to the posted code.
Epsilon Vector