2

I'm trying to make a Prolog predicate iscontained/2: iscontained(List, Search) where it returns true. if the Search is listed within the given List, false. if not. And if it is a variable that is inputted, then it just returns that it equals each element in the list.

Example:

?- iscontained([a, b, c], a).

true.

?- iscontained([a, b, c], d).

false.

?- iscontained([a, b, c], A).

A = a;
A = b;
A = c;
false.

I need a shove in the right direction, not asking for a hand out, unless you know a quick way to do it. Any help is appreciated, thanks.

false
  • 10,264
  • 13
  • 101
  • 209
  • 1
    btw the `member/2` predicate does just that, although with switched parameters. – m09 Mar 22 '12 at 01:26

3 Answers3

3

Please note that the frequently proposed member/2 predicate admits solutions that are no lists at all:

?- member(e,[e|nonlist]).
   true.

This is not a big problem in many situations, but should be mentioned nevertheless.

A natural, symmetric definition that only admits lists uses DCGs:

... --> [] | [_], ... .

iscontained(Es, E) :-
   phrase((...,[E],...), Es).

The ... is a non-terminal which denotes an arbitrary sequence.

While this is entirely overkill for this tiny example, it gives you a template for more interesting patterns. Like

iscontainedtwice(Es, E) :-
   phrase((...,[E],...,[E],...), Es).
false
  • 10,264
  • 13
  • 101
  • 209
2

You will need to consider two cases. I'll leave the body of the rules up to you.

  • iscontained([A|Xs],A)
  • iscontained([X|Xs],A)

[edited to remove reference to the empty list: the empty list contains nothing: if encountered, the predicate fails.]

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
Nick Barnes
  • 19,816
  • 3
  • 51
  • 63
2

Now that you certainly already came up with a solution, I'd like to mention one thing:

The classical version:

member(Item, [Item|_List]).
member(Item, [_Head|List]) :- member(Item, List).

leaves a choice point after having found the last element possible, ie:

?- member(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3;
false.

while

member2(Item, [Head|List]) :-
    member2(List, Item, Head).

member2(_List, Item, Item).
member2([Head|List], Item, _PreviousHead) :-
    member2(List, Item, Head).

treats the empty list at the same time as the last element and allows optimization:

?- member2(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3.

That's the version used in SWI-Prolog (and certainly Jekejeke Prolog and maybe others). Its author is Gertjan van Noord.

That's just meant as a reminder that, while the exercise of coming up yourself with a member/2 implementation is excellent, it should not lead you not use the built-ins afterwards, they're often fine tuned and more efficient!

m09
  • 7,490
  • 3
  • 31
  • 58
  • Yep, http://stackoverflow.com/questions/8436568/code-for-member-2-with-some-determinism –  Feb 28 '15 at 11:47