尝试在Prolog中实现获取列表的第n个元素

尝试在Prolog中实现获取列表的第n个元素,prolog,Prolog,我对Prolog非常陌生,并试图在Prolog中实现get列表的第n个元素 这是我的代码,但它抛出了错误 element_at(X,[X|_],1). element_at(X,[_|L],K) :- K > 1, K1 is K - 1, element_at(X,L,K1). 我认为代码右侧第二行中的X必须替换为其他东西,但我想不出任何东西 K在测试时不进行评估。 你需要颠倒顺序 element_at(X,[X|_],1). element_at(X,[_|L],K

我对Prolog非常陌生,并试图在Prolog中实现get列表的第n个元素 这是我的代码,但它抛出了错误

element_at(X,[X|_],1).
element_at(X,[_|L],K) :-
   K > 1,
   K1 is K - 1,
   element_at(X,L,K1).

我认为代码右侧第二行中的X必须替换为其他东西,但我想不出任何东西

K在测试时不进行评估。 你需要颠倒顺序

element_at(X,[X|_],1).
element_at(X,[_|L],K) :- element_at(X,L,K1), K is K1 + 1.

这是一个使用累加器的尾部递归版本。使用累加器,它的值已经在每次调用中实例化,因此您可以先递增,然后执行递归

element_at(X, List, Pos) :-
    element_at(X, List, 1, Pos).
element_at(X, [X|_], Pos, Pos).
element_at(X, [_|T], Acc, Pos) :-
    Acc1 is Acc + 1,
    element_at(X, T, Acc1, Pos).
这适用于输入上的各种变量组合,但如果
Pos
接地并找到可能的解决方案后,它(以及Capelical的非尾部递归版本)将无限循环,例如:

| ?- element_at(X, L, 3).

L = [_,_,X|_] ? ;
.... loop ....
因此,检查这种情况的修改可以避免:

element_at(X, List, Pos) :-
    element_at(X, List, 1, Pos).
element_at(X, [X|_], Pos, Pos).
element_at(X, [_|T], Acc, Pos) :-
    (nonvar(Pos) -> Acc < Pos ; true),  % fail if Acc hits ground Pos
    Acc1 is Acc + 1,
    element_at(X, T, Acc1, Pos).
以及:


对不起,如果我没有用那句话取笑你,顺便说一句;我觉得我很有趣$@意志力无忧。这很有趣。在评论中很难说出意图。但我开始重新考虑我的帖子,尤其是在你得到了一个简洁的答案之后。开场白上的观众太多了,所以我不敢肯定我希望不是我。至少我从来没有想过他们(我们…)并不像我有时想的那样,真的;但是,他们离comp.lang.lisp曾经的样子还有很长的路要走(也许现在仍然是,我不知道)@意志哦。。。我去过一些
comp.lang
团体。他们可以得到。。。有趣的。:)@尼古拉斯·卡利:你的缩进风格很有争议。如果你把它放在你的代码上没关系,但是你把它放在别人的代码上
| ?- element_at(X, L, 3).
L = [_,_,X|_] ? ;
no.
| ?- element_at(X, L, P).
L = [X|_]
P = 1 ? ;
L = [_,X|_]
P = 2 ? ;
L = [_,_,X|_]
P = 3 ? ;
L = [_,_,_,X|_]
P = 4 ? ;
...etc...