Почему этот код Пролога не работает?

у меня есть код пролога, который находит K-й элемент данного списка.

этот код не работает.

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

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

но когда я немного изменил этот код, он работает.

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

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

зачем нужна такая штука как К1?


person Bilal Yasar    schedule 13.03.2014    source источник


Ответы (1)


Если вы передаете такое выражение, как K-1, в качестве аргумента предикату в прологе, пролог не вычисляет выражение, как в других языках. Он передается как термин '-'(K,1) с экземпляром K, как указано в вашем предикате.

Итак, предположим, вы запросили:

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

Тогда ваш запрос будет соответствовать второму предложению вашего предиката:

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

И рекурсивно запросить:

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

Это снова будет соответствовать второму предложению и запросить:

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

Который потерпит неудачу, поскольку он не соответствует ни одному из ваших пунктов.

Поэтому, если вы хотите передать значение выражения в качестве аргумента, вам необходимо выполнить предварительную оценку, как вы сделали с K1:

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

Обратите внимание, что у вас может быть отложенная оценка. Например:

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

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

X = 1
Y = -4

yes
| ?-

В этом случае, когда запрашивается foo, он запрашивает как foo(1-3, Y). Когда выполняется foo, выполняется строка: Y is X * 2, которая оценивает, Y is (1-3)*2 дает Y=-4.

person lurker    schedule 13.03.2014