The implementation given by @chamini2 is impure, and can become logically unsound when working with non-ground terms. Consider the following two queries:
?- E=1, remove_first_X(E,Xs,[2,1,0]).
E = 1, Xs = [1,2,1,0] ;
E = 1, Xs = [2,1,1,0] ;
false.
?- remove_first_X(E,Xs,[2,1,0]), E=1.
E = 1, Xs = [1,2,1,0] ;
false. % one solution is missing!
prolog-dif to the rescue!
By replacing (\=)/2
with dif/2
, the code gets logically pure:
remove_1st_x(X,[X|Xs],Xs).
remove_1st_x(X,[Y|Xs],[Y|Ys]) :-
dif(X,Y),
remove_1st_x(X,Xs,Ys).
Let's run above queries again, this time with the improved implementation:
?- E=1, remove_1st_x(E,Xs,[2,1,0]).
E = 1, Xs = [1,2,1,0] ;
E = 1, Xs = [2,1,1,0] ;
false.
?- remove_1st_x(E,Xs,[2,1,0]), E=1.
E = 1, Xs = [1,2,1,0] ;
E = 1, Xs = [2,1,1,0] ;
false.
That's better! And the other queries given by the OP also work like they should:
?- remove_1st_x(1,[1,2,3],[2,3]).
true ;
false.
?- remove_1st_x(1,[2,1,3],[2,3]).
true ;
false.
?- remove_1st_x(1,X,[2,1,0]).
X = [1,2,1,0] ;
X = [2,1,1,0] ;
false.
Edit 2015-05-07
Above implementation of remove_1st_x/3
leaves behind a useless choice-point when it could succeed deterministically.
Let's get rid of that inefficiency while preserving logical-purity!
Using if_/3
and reified equality (=)/3
(a.k.a. equal_truth/3
), as defined by @false in an answer to question "Prolog union for A U B U C", we can define remove_1st_x/3
like this:
remove_1st_x(E,[X|Xs],Ys) :-
if_(X=E, Xs=Ys, (Ys=[X|Ys0],remove_1st_x(E,Xs,Ys0))).
Let's run above queries again! Note that all succeed deterministically.
?- remove_1st_x(1,[2,1,3],Ys).
Ys = [2,3].
?- remove_1st_x(1,[2,1,3],[2,3]).
true.
?- remove_1st_x(1,[1,2,3],[2,3]).
true.