1

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

4

3 回答 3

2

借助SWI-Prolog 中可用的声明性算术:

:- [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.
于 2013-04-07T20:56:05.070 回答
1

它不是那样工作的,因为为了使 Prolog 中的算术可行,您没有将正整数定义为 0 的后继。因此,对于算术比较,您需要两边都是有效的算术表达式,并且对于succ(N,N1)谓词在 SWI 中可用(例如 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 为种子,以便它可以计算当前正在比较的元素的索引。

于 2013-04-07T19:00:10.463 回答
0

如果您查看您的代码,您会看到 K 在 x 是列表的第一个元素时被初始化。如果不是这种情况,则增加 K。如果调用谓词时 x 不是列表的第一个元素,则 K 没有值!

于 2013-04-07T18:46:11.593 回答