为什么这个Prolog代码不起作用?

时间:2014-03-13 12:07:21

标签: prolog

我有一个prolog代码,可以找到给定列表的Kth元素。

此代码无效。

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).

为什么我们需要像K1这样的东西?

1 个答案:

答案 0 :(得分:0)

如果将诸如K-1之类的表达式作为参数传递给prolog中的谓词,则prolog不会像在其他语言中一样评估表达式。它已作为术语'-'(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