list_sum([], 0).
list_sum([Head | Tail], TotalSum) :-
list_sum(Tail, Sum1),
Total = Head + Sum1.
此代码返回true
。如果我将Total = Head + Sum1
替换为Total is Head + Sum1
,则会返回该值。但是我应该用它替换它来得到这样的结果:
?- list_sum([1,2,0,3], Sum).
Sum = 1+2+0+3 ; % not to return value 6!!!
答案 0 :(得分:21)
答案很简单:
sum_list([], 0).
sum_list([H|T], Sum) :-
sum_list(T, Rest),
Sum is H + Rest.
此代码仅在一个方向上起作用 - 这意味着 - 它不允许您生成具有该特定总和的列表。但由于这些列表的集合是无限的,所以无论如何这都不实用。
答案 1 :(得分:8)
请注意,在您的过程的第二个子句中,TotalSum永远不会被实例化。在咨询您的代码时,您应该已经收到口译员的警告。
这是我的建议:
list_sum([Item], Item).
list_sum([Item1,Item2 | Tail], Total) :-
list_sum([Item1+Item2|Tail], Total).
第一个子句处理基本情况,当列表中只剩下一个元素时,就是你的结果。
第二个子句涉及递归步骤。它抓取列表的前两项并执行递归调用,用新术语Item1 + Item2替换这两项。
答案 2 :(得分:2)
在Prolog中(+)/2
是二进制中缀运算符。这允许我们编写A+B
而不是+(A,B)
。
?- current_op(_,yfx,+). % left-associative binary infix operator true.
(+)/2
关联到左侧,因此1+2+3
是(1+2)+3
的缩写。
(.)/2
与权利相关联,因此[1,2,3]
是.(1,.(2,.(3,[])))
的缩写。
为了使括号正确,我们使用带有额外“accumulator”参数的辅助谓词:
list_sum([X|Xs],S) :-
list_sum0_sum(Xs,X,S).
list_sum0_sum([], S ,S).
list_sum0_sum([X|Xs],S0,S) :-
list_sum0_sum(Xs,S0+X,S).
示例查询:
?- list_sum([1,2,0,3],S).
S = 1+2+0+3.
答案 3 :(得分:1)
如果要将数字列表转换为加法表达式,请从
开始[1,2,3]
到
1 + 2 + 3
你可以使用像差异列表这样的东西来做这样的事情:
list_to_additive_expr( [] , 0 ).
list_to_additive_expr( [X|Xs] , X + RHS ) :-
sum_of( Xs , RHS ).
或者,您可以使用累加器:
list_to_additive_expr( Xs , Expr ) :-
list_to_additive_expr( Xs , 0 , Expr )
.
list_to_additive_expr( [] , Expr , Expr ) .
list_to_additive_expr( [X|Xs] , RHS , Expr ) :-
sum_of( Xs , X + RHS , Expr )
.
我相信你会发现第一个样式没有正确尾递归,所以不会通过尾递归优化(TRO)优化成循环 - 和所以,如果列表足够长,将会出现堆栈溢出。第二种方法应该应用TRO,并且应该适用于任何长度的列表。
你可能会问,什么是TRO?这是Wikipedia with an answer for you:
在计算机科学中,尾调用是在另一个内部发生的子程序调用 过程并产生一个返回值,然后立即返回 呼叫程序。然后称呼叫站点处于尾部位置,即在尾部位置 调用程序。如果子例程对自身执行尾调用,则调用它 尾递归。这是递归的特例。
尾调用非常重要,因为它们可以在不添加新堆栈的情况下实现 框架到调用堆栈。当前程序的大部分框架都不需要任何框架 更多,它可以被尾调用的帧替换,并根据需要进行修改 (类似于进程的覆盖,但用于函数调用)。然后该程序可以跳转到 被调用的子程序。调用生成此类代码而不是标准调用序列 尾调用消除或尾调用优化。
答案 4 :(得分:1)
该计划
list_sum([],0).
list_sum([Head|Tail], TotalSum):-
list_sum(Tail, Sum1),
TotalSum is Head+Sum1.
现在,如果查询是
?- list_sum([1,2,3,4], Sum).
答案是
Sum = 10