@gusbro 说了什么。此外,您需要重新排列操作顺序并添加一些额外的特殊情况来处理不同长度的列表:
list_sum( [] , [] , [] ) .
list_sum( [] , [Y|Ys] , [Z|Zs] ) :- Z is 0+Y , list_sum( [] , Ys , Zs ) .
list_sum( [X|Xs] , [] , [Z|Zs] ) :- Z is X+0 , list_sum( Xs , [] , Zs ) .
list_sum( [X|Xs] , [Y|Ys] , [Z|Zs] ) :- Z is X+Y , list_sum( Xs , Ys , Zs ) .
您需要Z is X+Y
在上面的示例中移动评估 ( ),以便在递归之前Z
对其进行评估。这完成了两件事:
首先,它使谓词tail-recursive,这意味着解决方案是迭代的,因此不会消耗堆栈空间。在您的代码中,直到整个递归完成后才会执行评估。每个中间和都保存在堆栈中,并在您备份的过程中从右到左进行评估。这意味着你会在一个大名单上炸掉你的筹码。
其次,在递归之前评估每个结果意味着你很快就会失败。与结果不统一的第一个总和使整个操作失败。您的解决方案失败缓慢。考虑 10,000,000 个项目列表,其中第一个项目的总和不等于结果列表中的第一个项目:您将遍历所有 10,000,000 个项目,然后——假设你没有破坏你的堆栈——你开始从右到左计算总和。在最后一次评估之前,您的谓词不会失败。