memb/2 as given is often used and is frequently included in Prolog
libraries. We can use it as the base of an example to show how to
extend a procedure. Suppose we want to know the position at which
an item occurs. We will accept that if the element occurs in the list
of the goal, the procedure will write the position of that element
(taking the first element as one, rather than zero), and that if an
element doesn't occur in the list, then the goal will fail.
We need to add some extra processing to both clauses and, of course,
an extra argument. We'll look first at the recursive rule. Here
we need just add one to a counter each time we recurse:
% 2 recursive
memb(Elem, [_|Tail], Cnt) :-
Cnt1 is Cnt + 1,
memb(Elem, Tail, Cnt1).
The terminating clause can just write the position:
% 1 terminating condition
memb(Elem, [Elem|_], Cnt) :-
write(Cnt),
nl.
Putting these two together, we have:
% 1 terminating condition
memb(Elem, [Elem|_], Cnt) :-
write(Cnt),
nl.
% 2 recursive
memb(Elem, [_|Tail], Cnt) :-
Cnt1 is Cnt + 1,
memb(Elem, Tail, Cnt1).
Try the following goals:
| ?- memb(gamma, [alpha, beta, gamma], 1).
| ?- memb(alpha, [alpha], 1).
| ?- memb(delta, [alpha, beta, gamma], 1).
| ?- memb(alpha, [], 1).
We have defined memb/2 and memb/3. Prolog doesn't confuse the two
because, although they have the same functor, they have different
arities. However, it is a bit irritating to have to type the ',
1' each time and we have to ensure that each time we get it correct.
It is more convenient to write an extra, "calling" rule that supplies
the extra argument for us. However, we can't call this memb/2, because
this time Prolog will confuse it with our previous definition of memb/2,
So we will call this one memb_count/2:
% 1
memb_count(Elem, List) :-
memb(Elem, List, 1).
Try the following goals to assure yourself they give the same solutions
as before:
| ?- memb_count(gamma, [alpha, beta, gamma]).
| ?- memb_count(alpha, [alpha]).
| ?- memb_count(delta, [alpha, beta, gamma]).
| ?- memb_count(alpha, []).
|