4

使用 SWI Prolog,有一个谓词可以在名为 nth1 的列表中找到第 n 个项目。我想实现我自己的谓词版本,但是如果您查看清单(nth1)代码,SWI 就非常复杂。有没有更简单的方法呢?

谢谢 :)。

4

3 回答 3

4

考虑对一般(可逆)整数算术使用有限域约束:

:- use_module(library(clpfd)).

nth1(1, [E|_], E).
nth1(N, [_|Xs], E) :-
        N #> 1,
        N #= N1 + 1,
        nth1(N1, Xs, E).
于 2010-11-21T14:50:10.210 回答
2

我并不是故意要自相矛盾或让别人实际做我的工作。我只是想要一些建议,抱歉没有更清楚。

我现在自己实现了它,但你们能提出改进或更好的方法吗?我经常发现自己在 Prolog 中所做的事情是用一个计数器或一组计数器编写一个谓词,并获得一个参数较少的谓词来调用带有额外参数的子句。这通常最终会产生相当多的代码。无论如何,这是我刚刚做的实现:

item_at( N, L, Item ) :-
    item_at( N, 0, L, Item ).   
item_at( N, Count, [H|_], Item ) :-
    CountNew is Count + 1,
    CountNew = N,
    Item = H.
item_at( N, Count, [_|T], Item ) :-
    CountNew is Count + 1,
    item_at( N, CountNew, T, Item ).

任何意见?谢谢 :)。用法:

?- item_at(3,[a,b,c,d,e],Item).
Item = c ;
于 2010-11-21T12:34:40.980 回答
2

SWI 代码有点复杂,因为谓词可用于从变量索引生成:

?- nth1(Idx,[a,b,c],X).
Idx = 1,
X = a ;
Idx = 2,
X = b ;
Idx = 3,
X = c ;
false.

如果您不想要这种行为,nth1/3可以通过以下方式轻松实现nth0

nth1(Idx,List,X) :-
    Idx0 is Idx-1,
    nth0(Idx0,List,X).

编辑:也可以不用nth0几行代码:

nth1(1,[X|_],X) :- !.
nth1(Idx,[_|List],X) :-
    Idx > 1,
    Idx1 is Idx-1,
    nth1(Idx1,List,X).
于 2010-11-21T12:04:40.037 回答