为什么这个prolog函数不能返回所有有效值? (参数没有充分实例化)

时间:2013-04-07 18:16:48

标签: prolog

我正在研究我在网上找到的一个例子,试图了解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的有效值?

3 个答案:

答案 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/3nth1/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没有值!