我有一个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这样的东西?
答案 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
。