1

I have written a member function, to check if an element exists in a list.

member(X, [X|_]).
member(X, [_|Y]) :- member(X, Y).

I load the .pl file into SWI prolog, and I get no warnings or errors pertaining to member. I test the member function using...

member(A, [1,2,3,4]).

This, obviously should return false. Instead I get

 A = 1

Then when I try to enter new commands, the ide just shows me the key I typed, and says unknown action "what ever key i pressed"

I think my member function is sound, as it matches one written by my professor.

Any ideas?

Ryan Miles
  • 13
  • 2
  • 2
    Why should `member(A, [1,2,3,4])` *obviously return false*? It should obviously succeed for `A = 1` as well as for `A = 2`, `A = 3`, and `A = 4`. When it shows `A = 1` you need to press SPACE or `;` to see the next result, if there is one (per the Prolog documentation). – lurker Apr 15 '17 at 02:40
  • 1
    The chances are, this predicate was not written by your professor. `member/2`, with this implementation, has been around for decades I think? I've seen it in a dead tree textbook published in 1986 but I guess it predates the book. –  Apr 15 '17 at 08:08
  • @Boris: It is pretty recent ~less than 10 years that `member/2` became a true built-in. So it is quite natural to provide its definition. – false Apr 15 '17 at 16:44
  • @false In SWI-Prolog it is not a true built-in, it is defined in a library. The same for YAP I think. I don't know the GNU-Prolog implementation but there it shouldn't matter, right? Still, my point was rather that this definition has been around for quite a while. –  Apr 15 '17 at 17:10
  • @Boris: In SWI you can still add your own definition of `member/2`, like `member(1,2).` However, once you used the implicitly defined version, you are stuck with it. It is a built-in (that you cannot redefine) in SICStus 4. In YAP it is not defined at all (at least the version I tried, YAP has recently some strange changes that makes it difficult to follow). In GNU it cannot be redefined. Anyway, at least the Prolog prologue provides the first [complete defnition](http://www.complang.tuwien.ac.at/ulrich/iso-prolog/prologue#member). – false Apr 15 '17 at 19:53
  • @Boris, AFAIK in SWI Prolog built-in's are also implemented in the library. But they can be autoloaded (library usage may not be declared). About implementation of `member/2` in SWI and others: It's just a syntactic sugar or whatever you want sugar ;). Take any else predicate or create your own with similar semantic you will see how it behaves (when failure isn't hidden. http://www.swi-prolog.org/pldoc/man?predicate=member/2 – Anton Danilov Apr 16 '17 at 05:22
  • @AntonDanilov I am not sure what you mean by "syntactic sugar". If you look at the [standard library implementation](https://github.com/SWI-Prolog/swipl-devel/blob/3bb20443c682b78c2cc6f8add52ac779f9cf7919/library/lists.pl#L98-L116) you should notice that it is indeed different from the one shown here, in order to get rid of the choice point in some cases. –  Apr 16 '17 at 05:29
  • @AntonDanilov I guess I have been using "built-in" to mean "implemented in the underlying language (C)", and "library predicate" to mean "implemented in Prolog". I really don't know if this is at all correct.... –  Apr 16 '17 at 05:31

1 Answers1

0

You have called predicate member/2 in the i/o mode(o, i) e.i. first argument free (unbound) variable and the second is bound variable.

In that mode (despite its name) member/2 actually doesn't test element against list membership but simply enumerates list elements one-by-one and, finally, when no elements are remained, it fails (predicates fail in terms of logic programming, not return false ).

This predicate often used in so called failure driven control technique, e.g.:

trivial example when enumerated list elements are simply written

 ?- forall( member(X, [1,2,3,4]), write( X ) ).

Note, in this case will be no failure after list is exhausted. To ensure this, the last clause is added, such that is meaning "the predicate successed at all".

 p( List, Action ) :- generator( Variant, List ), side_effect_action( Variant ), fail.
 p( _ , _ ).

 generator( X, L ) :- member( X, L ).
Anton Danilov
  • 1,246
  • 11
  • 26
  • The documentation to `member/2` is usually quite (too?) succint, see for example the [SWI-Prolog manual](http://eu.swi-prolog.org/pldoc/doc_for?object=member/2): "True when `Elem` is a member of `List`". When `Elem` is a variable, "is a member" translates to "unifies with member". I am pointing this out just to make clear that nothing in the implementation or documentation of `member/2` claims that it only tests whether a ground element is inside a ground list. –  Apr 15 '17 at 09:06
  • Agree. I only meant (by my personal expierence) that member/2 may be interpeted lop-sidely due to its typical usage (X is member of Xs) . – Anton Danilov Apr 15 '17 at 09:40
  • Typically, if you want to test for membership of a ground element in ground list you'd take `memberchk/2` since it is both more efficient and leaves no choice points. All the uses of `member/2` that **cannot** be replaced by `memberchk/2` involve a first argument that is **not** ground; for example, `?- member(a(X), [a(1), b(2), a(3)])`. –  Apr 15 '17 at 09:50
  • Although I gotta say, "X **is** member of Xs" already hints that what is meant is "X unifies with element(s) of Xs". There are a few of those in the SWI-Prolog documentation, and I think elsewhere too. For example, "`min_member(Min, List)` True when Min is the smallest member in the standard order of terms." but then: `?- min_member(2, [1, X]). X = 2.` (!?!) –  Apr 15 '17 at 09:58
  • @Boris In my answer I told about non-ground first sargument and ground list. For me, it's the one of typical usages too. :) – Anton Danilov Apr 15 '17 at 10:00
  • I already gave you an upvote because I thought it is a good answer :-) –  Apr 15 '17 at 10:02
  • I am not sure I know what you mean by "appropriate" and how to mark it. BTW, the last part of your answer is a bit dubious and I am not sure I understand it. Do you mean to say that you try to manually add the trailing choice point even if it is not there? –  Apr 15 '17 at 10:08
  • @Boris I 'm about this: One can generate members of a list: ?- member(X,[1,2,3]). X = 1 ; X = 2 ; X = 3 ; No https://www.cpp.edu/~jrfisher/www/prolog_tutorial/2_7.html – Anton Danilov Apr 15 '17 at 11:54
  • If you try the library version of `member/2` in SWI-Prolog you will see there is no "No" or "false" after the last solution. So I still don't understand if you think this is the _desired_ behaviour and trying to emulate it, or if there is something more going on. –  Apr 15 '17 at 11:56
  • 1
    I wouldn't really refer to `member(A, [1,2,3,4])` as a *mode of operation*. In Prolog, a query is a query and Prolog simply tries to make that query succeed and will instantiate any variables, if it can, in order to result in that success. Querying `member(1, [1,2,3,4])` simply succeeds. Querying `member(A, [1,2,3,4])` succeeds if Prolog instantiates `A` with 1, 2, 3, or 4. And `member(1, L)` succeeds on `L` of `[1|_]`, `[_,1|_]`, `[_,_,1|_]`, etc... – lurker Apr 15 '17 at 12:02
  • 1
    @lurker I am not sure how you mean it, but querying `member(1, [1,2,3,4])` succeeds with a choice point, and fails if backtracked into. Which is why the whole [`memberd/2` story](http://stackoverflow.com/q/30924607/1812457) –  Apr 15 '17 at 13:30
  • 1
    @Boris yes you're right, I was a little sloppy with my words of "simply succeeds". I guess it succeeds but not so simply. :) My overall point, though, was that there aren't different "modes" of operation for a predicate. – lurker Apr 15 '17 at 13:46