以下谓词的目标是选择列表的前N个项目。应该将其分配给输出变量,但是事实并非如此。
firstx(N, [H|T], L) :-
(
length(L, Le), Le < N ->
append(L, [H], O),
firstx(N, T, O)
;
write(L)
).
这是上述谓词的输出
?- firstx(2, [1,2,3,4,5], X).
[1,2],
X = [].
这应该是
?- firstx(2, [1,2,3,4,5], X).
[1,2],
X = [1,2].
如图所示,最后一个变量未正确分配。您对如何编程有什么建议?预先感谢!
答案 0 :(得分:1)
我对您编写的代码感到困惑。我看不到您在firstx(N, T, O)
中进行递归的基本情况。 N
永远不会减少,尽管您将项目从第二个位置剥离出列表,但没有理由认为该列表为空。您使用append/3
的目的是试图将项目放在结果列表的末尾,但是您也正在构造L
。最终,我认为您的问题与可能有关,因为您将第三个参数的新变量传递给递归调用(最终将其写出),但您没有返回O
,您将返回L
。我猜想如果将L
替换为O
,这是行不通的,因为在启动查询时必须将其实例化,而必须在递归调用中实例化该变量。
我不太确定您要使用此代码做什么。我看到两种清晰的实现方法:递归谓词或使用append/3
,并且在您的解决方案中看到了两者的元素。因此,让我与您分享我所看到的两种方法。
递归方法如下:
firstx(0, _, []).
firstx(N1, [H|T], [H|R]) :-
succ(N0, N1),
firstx(N0, T, R).
在此解决方案中,我们将列表开头的项目一一列出。使用succ/2
是一个好习惯,因为与N0 is N1 - 1
不同,它实际上可以双向使用。当我在您的子句的开头看到[H|T]
时,我认为这是您要去的地方,但是同样,我怀疑您没有以类似的方式构建L
不会在递归调用中减少N
。
append/3
方法如下:
firstx(N, L, FirstN) :-
length(FirstN, N),
append(FirstN, _, L).
由于您可以使用length/2
列出任意长度的变量,然后让append/3
为您完成所有统一操作,因此这是一种更为优雅的解决方案。