以下谓词的目标是选择列表的前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].
如图所示,最后一个变量没有正确赋值。你对它应该如何编程有什么建议吗?提前感谢!
发布于 2019-02-28 23:32:34
我被你写的代码搞糊涂了。我在firstx(N, T, O)
中看不到递归的基本情况。N
永远不会减少,尽管您在第二个位置从列表中剥离了项,但当该列表为空时,您没有理由这样做。您使用append/3
似乎是为了将项目放在结果列表的末尾,但您也在构造L
。最终,我认为您的问题可能与以下事实有关:您正在将第三个参数的新变量传递给递归调用(它最终会将其写出),但您返回的不是O
,而是L
。我猜如果用O
替换L
,这就不起作用了,因为在开始查询时必须取消实例化变量,但在递归调用中实例化了它。
我真的不知道你想用这段代码做什么。我看到了两种明确的实现方法:递归谓词,或者使用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
为您完成所有的统一工作。
https://stackoverflow.com/questions/54928883
复制相似问题