递归谓词的输出

时间:2019-02-28 15:16:45

标签: list recursion prolog

以下谓词的目标是选择列表的前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].

如图所示,最后一个变量未正确分配。您对如何编程有什么建议?预先感谢!

1 个答案:

答案 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为您完成所有统一操作,因此这是一种更为优雅的解决方案。