Reputation: 183
I am very new in Prolog and trying to implement get the nth element of a list in Prolog here is my code but it throws error
element_at(X,[X|_],1).
element_at(X,[_|L],K) :-
K > 1,
K1 is K - 1,
element_at(X,L,K1).
I think that X in the second line in the right side of the code has to be replaced with some thing else but I could not think of any .
Upvotes: 2
Views: 8349
Reputation: 58234
Here is a tail-recursive version using an accumulator. Using the accumulator, its value is instantiated already on each call so you can increment first, then do the recursion.
element_at(X, List, Pos) :-
element_at(X, List, 1, Pos).
element_at(X, [X|_], Pos, Pos).
element_at(X, [_|T], Acc, Pos) :-
Acc1 is Acc + 1,
element_at(X, T, Acc1, Pos).
This works with various combinations of variables on the input, but it (as well as CapelliC's non-tail recursive version) will loop infinitely if Pos
is ground and after a possible solution is found, such as with:
| ?- element_at(X, L, 3).
L = [_,_,X|_] ? ;
.... loop ....
So a modification to check for this case avoids that:
element_at(X, List, Pos) :-
element_at(X, List, 1, Pos).
element_at(X, [X|_], Pos, Pos).
element_at(X, [_|T], Acc, Pos) :-
(nonvar(Pos) -> Acc < Pos ; true), % fail if Acc hits ground Pos
Acc1 is Acc + 1,
element_at(X, T, Acc1, Pos).
Now you get:
| ?- element_at(X, L, 3).
L = [_,_,X|_] ? ;
no.
And:
| ?- element_at(X, L, P).
L = [X|_]
P = 1 ? ;
L = [_,X|_]
P = 2 ? ;
L = [_,_,X|_]
P = 3 ? ;
L = [_,_,_,X|_]
P = 4 ? ;
...etc...
Upvotes: 1
Reputation: 60004
K is not evaluated when you test it. You need to reverse the order
element_at(X,[X|_],1).
element_at(X,[_|L],K) :- element_at(X,L,K1), K is K1 + 1.
Upvotes: 5