我正在研究我在网上找到的一个例子,试图了解Prolog的回归。这里的代码......
element_at(X,[X|_],1).
element_at(X,[_|L],K) :-
K > 1,
K1 is K - 1,
element_at(X,L,K1).
这有效......
?- element_at(x, [a,b,c,x,x,d,e], Pos).
但这不是......我希望此代码返回有效值列表,例如......
?- element_at(x, [a,b,c,x,x,d,e], Pos).
Pos = 4;
Pos = 5;
但我获得ERROR: >/2: Arguments are not sufficiently instantiated
我要更改什么才能让它返回Pos
的有效值?
答案 0 :(得分:2)
借助SWI-Prolog中提供的declarative arithmetic:
:- [library(clpfd)].
element_at(X,[X|_],1).
element_at(X,[_|L],K) :-
K #> 1,
K1 #= K - 1,
element_at(X,L,K1).
我们得到了预期的声明性行为:
?- element_at(x, [a,b,c,x,x,d,e], Pos).
Pos = 4 ;
Pos = 5 ;
false.
答案 1 :(得分:1)
它不能像那样工作,因为,为了使Prolog中的算术可行,你没有将正整数定义为0的后继。因此,对于算术比较,你需要双方都是有效的算术表达式,并且对于SWI中可用的succ(N,N1)
谓词(使N1为N + 1),您需要至少实例化两个参数中的一个。
SWI的谓词nth0/3
和nth1/3
完全符合您的要求(参数顺序略有不同)。它在Prolog中实现,它的作用是,它查看N是变量还是正整数,然后调用返回所有索引的生成nth
或确定性nth
选择第N个元素。
这是从SWI-Prolog源代码中的lists.pl复制而来的!
nth0(Index, List, Elem) :-
( integer(Index)
-> nth0_det(Index, List, Elem) % take nth deterministically
; var(Index)
-> List = [H|T],
nth_gen(T, Elem, H, 0, Index) % match
; must_be(integer, Index)
).
注意nth_gen
如何用0播种,以便它可以计算当前比较的元素的索引。
答案 2 :(得分:0)
如果查看代码,当x是列表的第一个元素时,您会看到K已初始化。 如果不是这种情况,K会递增。如果在调用谓词时x不是列表的第一个元素,则K没有值!