0
votes

i have a prolog code that finds Kth element of a given list.

this code doesnt work.

element_at(X,[X|_],1) :- !.

element_at(X,[_|T],K) :-  element_at(X,T,K-1).

but when i modified this code a little bit, then works.

element_at(X,[X|_],1) :- !.

element_at(X,[_|T],K) :-  K1 is K-1,element_at(X,T,K1).

why we need such a thing like K1?

1

1 Answers

0
votes

If you pass an expression such as K-1 as an argument to a predicate in prolog, prolog does not evaluate the expression as in other languages. It's passed as the term '-'(K,1) with K instantiated as indicated in your predicate.

So, let's suppose you queried:

element_at(X, [1,2], 2).

Then your query would match the second clause of your predicate:

element_at(X,[_|T],K) :- element_at(X,T,K-1).

And recursively query:

element_at(X, [2], 2-1).

This would match the second clause again and query:

element_at(X, [], 2-1-1).

Which will fail since it doesn't match any of your clauses.

Therefore, if you want to pass the value of an expression as an argument, you need to pre-evaluate, as you have done with K1:

K1 is K-1,
element_at(X, T, K1).

Note that you could have a deferred evaluation. For example:

foo(X, Y) :-
    Y is X * 2.

| ?- X = 1, foo(X-3, Y).

X = 1
Y = -4

yes
| ?-

In this case, when foo is queried, it queries as, foo(1-3, Y). When foo executes, it executes the line: Y is X * 2 which evaluates, Y is (1-3)*2 yielding Y=-4.