Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement the member predicate as a one-liner

Tags:

list

prolog

dcg

Interview question!

This is how you normally define the member relation in Prolog:

member(X, [X|_]).        % member(X, [Head|Tail]) is true if X = Head                           % that is, if X is the head of the list member(X, [_|Tail]) :-   % or if X is a member of Tail,   member(X, Tail).       % ie. if member(X, Tail) is true. 

Define it using only one rule.

like image 591
Claudiu Avatar asked Nov 16 '09 19:11

Claudiu


People also ask

How does member work in Prolog?

If Term is a variable and List is a list, all the members of the list List are found on backtracking. If List is not instantiated, member/2 binds List to a new partial list containing the element Term. The definition of this Prolog library predicate is: member(X,[X|_]).

What does \+ mean in Prolog?

Because of the problems of negation-as-failure, negation in Prolog is represented in modern Prolog interpreters using the symbol \+ , which is supposed to be a mnemonic for not provable with the \ standing for not and the + for provable.

How do you check not a member of a list in Prolog?

Used to check that Element is not a member of the list List. The definition of this Prolog library predicate is: nonmember(Arg,[Arg|_]) :- !, fail. nonmember(Arg,[_|Tail]) :- !, nonmember(Arg,Tail).

How do you add to a list in Prolog?

You can't modify lists in Prolog, but you can create a list with an unspecified length: main :- A = [1,2,3,4|_]. Then, you can insert an element using nth0/3 in SWI-Prolog: :- initialization(main).


1 Answers

  1. Solution:

    member(X, [Y|T]) :- X = Y; member(X, T). 
  2. Demonstration:

    ?- member(a, []). fail. ?- member(a, [a]). true ; fail. ?- member(a, [b]). fail. ?- member(a, [1, 2, 3, a, 5, 6, a]). true ; true ; fail. 
  3. How it works:

    • We are looking for an occurrence of the first argument, X, in the the second argument, [Y|T].
    • The second argument is assumed to be a list. Y matches its head, T matches the tail.
    • As a result the predicate fails for the empty list (as it should).
    • If X = Y (i.e. X can be unified with Y) then we found X in the list. Otherwise (;) we test whether X is in the tail.
  4. Remarks:

    • Thanks to humble coffee for pointing out that using = (unification) yields more flexible code than using == (testing for equality).
    • This code can also be used to enumerate the elements of a given list:

      ?- member(X, [a, b]). X = a ; X = b ; fail. 
    • And it can be used to "enumerate" all lists which contain a given element:

      ?- member(a, X). X = [a|_G246] ; X = [_G245, a|_G249] ; X = [_G245, _G248, a|_G252] ; ... 
    • Replacing = by == in the above code makes it a lot less flexible: it would immediately fail on member(X, [a]) and cause a stack overflow on member(a, X) (tested with SWI-Prolog version 5.6.57).

like image 64
Stephan202 Avatar answered Sep 20 '22 20:09

Stephan202