我正在尝试在prolog中编写一个谓词来查找列表中的Kth元素。 例如:
?- element_at(X,[a,b,c,d,e],3).
X = c
我的代码如下
k_ele(X,[X|_],1).
k_ele(X,[_|T],Y) :- Y > 1,Y is Y - 1, k_ele(X,T,Y).
但没有用,我在互联网上找到了解决方案
element_at(X,[X|_],1).
element_at(X,[_|L],K) :- K > 1, K1 is K - 1, element_at(X,L,K1).
除了使用一个额外的变量K1之外,它与我的逻辑相同。
我的代码出了什么问题,为什么我需要另一个变量?
答案 0 :(得分:3)
您的代码不起作用的原因是统一不是一项任务。当你说
Y is Y - 1
您正试图将Y
的值与Y-1
的值统一,这在数学上是不可能的。这与说4 is 3
或1001 is 1000
大致相同。整个条件失败,导致无法在列表中找到元素。
您在互联网上找到的固定解决方案引入了一个单独的变量K1
,该变量与K - 1
统一。这是非常可行的:K1
获取K-1
计算的值,条件成功,并且子句移动到递归调用部分。
答案 1 :(得分:2)
因为prolog中的变量是一次性写入的生物。已经[赋值]一个非变量值,它不再是变量。从此以后就是这个价值。与更多...传统...编程语言不同,一旦绑定,重新分配prolog变量的唯一方法是回溯分配并撤消它。
应该注意的是,变量可以与另一个变量统一:给出类似
的谓词foo(X,Y) :- X = Y .
等等
shazam(X,Y) :- bar(X,Y) , X = 3.
将导致X和Y都为3.统一后,X和Y都是相同的变量,尽管名称不同。
答案 2 :(得分:1)
我想你正在使用这个链接的练习:
http://www.ic.unicamp.br/~meidanis/courses/problemas-prolog/
请注意,在我看来,原始解决方案也不是最好的。
例如,查询:
element_at(X,[a,b,c],Y).
即使有3个解决方案,也会崩溃:
我相信以另一种方式写作:
element_at(H, [H | _], 1).
element_at(H, [_ | T], N) :- element_at(H, T, NMinus1), N is NMinus1 + 1.
会给出更好的结果。由于无法应用最后一次调用优化,因此效率较低,但逻辑变得更加通用。