Search code examples
prolog

List_subset_of_list predicate with choice points?


So here's my subset predicate:

subset([],[_|_]).
subset([X|Ts],L) :-
    member(X,L),
    subset(Ts,L).

Here's the problem I get:

?- subset([1,2], [3,2,1]).
true ;
false.

Why did prolog keep looking for a solution when it'd already found one? I tried adding a cut in front of the first clause, but to no use!

Edit: format error was making the first clause not appear.


Solution

  • Because of what happens if there is more than one solution:

    member(4, [4, 0, 0, 4, 4])
               ^        ^  ^
    

    answers true for the first 4 and then if you ask it to retry, answers true for the next 4, and so on until the end. In your case there are no more solutions and it returns false when asked for more.

    It seems like that's a behaviour of member/2. Reading down to the comments there includes:

    "deterministic" means that the predicate succeeds exactly once (but may leave a choicepoint that, however, yields no further solution on backtracking) whereas

    "well-behaved deterministic" means that the predicate succeeds exactly once and leaves no choicepoint.

    and a suggestion:

    Use memberchk/2 if you are hunting for efficiency and a single solution is sufficient (but watch out for unexpected failures with memberchk/2)

    Swap memberchk for member in your code, and it answers without leaving a choicepoint.