这一行没有多大意义:
rowN(L,[],[]).
因为第二个参数是一个整数(如果我理解正确的话),并且你使用了一个列表。几乎所有的论点都是这种情况。此外,您在递归调用中使用RowI?
解决方案
一种解决方案是首先指定第一行(I = 1)等于矩阵的头部:
rowN([H|_],1,H).
接下来,您需要找到一种迭代方式来枚举您的矩阵。所以标题肯定是某种形式:
rowN([H|T],I,X) :-
# ...
现在我们假设I 不等于1(我们稍后会讨论这个话题)。在这种情况下,我们需要进一步遍历矩阵,因此我们将采用 tail 并将计数器 I 设置为倒数。这可以使用:
rowN([_|T],I,X) :-
I1 is I-1,
rowN(T,I1,X).
所以我们的谓词如下:
rowN([H|_],1,H).
rowN([_|T],I,X) :-
I1 is I-1,
rowN(T,I1,X).
现在如果你使用这个谓词,它会给出正确的结果:
?- rowN([[1,2],[3,4],[5,6]], 2, R).
R = [3, 4] ;
false.
问题是为什么谓词没有产生其他结果:在显示第一个结果后,对于rowN([[1,2],[3,4],[5,6]], 2, R) :- rowN([[3,4],[5,6]],1,[3,4]).,它可以尝试寻找替代方案。它通过使用第二个子句来做到这一点,但它最终会用完行并调用rowN([],_,_) 谓词,因为没有子句匹配,它将失败。
这个解决方案并不完美:它不能在所有方向都正确工作,这在 Prolog 中通常很难。这就是优秀的 Prolog 程序员编写库的原因。
您可以使用 swi-prolog 中的 nth1/3 谓词,而不是重新发明轮子。尽管交换了参数-您需要将其称为nth1(2,[[1,2],[3,4],[5,6]],R).-它的优点是它可以在大多数人可以在快速解决方案中提出的更多方向上工作,但几乎可以肯定没有错误(因为它已经过测试所有使用谓词的 Prolog 程序都有数十亿次),其中一些内置函数是用 C++ 实现的,这使得它们有时更快。例如:
?- nth1(2, [[1,2],[3,4],[5,6]], R).
R = [3, 4].
?- nth1(I, [[1,2],[3,4],[5,6]], [5,6]).
I = 3.
?- nth1(I, [[1,2],[3,4],[5,6]], R).
I = 1,
R = [1, 2] ;
I = 2,
R = [3, 4] ;
I = 3,
R = [5, 6].
?- nth1(I,M,[2,3]).
I = 1,
M = [[2, 3]|_G23] ;
I = 2,
M = [_G22, [2, 3]|_G26] ;
I = 3,
M = [_G22, _G25, [2, 3]|_G29] ;
I = 4,
M = [_G22, _G25, _G28, [2, 3]|_G32] .
因此,您可以询问第二行是什么,询问行 [5,6] 的位置,通过使用索引 I 和行 R 的元组回答来使查询更通用,并生成一个矩阵行[2,3]某处。