递归中的变量分配

时间:2018-12-15 04:30:38

标签: prolog

为此:

useAdd(List, What) :-                                         
    addToList(List, What, New),                               
    reverseList(New, T),                                      
    write("done "),                                           
    write(T), nl, !.                                          

addToList(List, What, [ What | List]).                        

reverseList([], List) :- write(List), nl.                     
reverseList([H | Old], []) :- reverseList(Old, [ H ]).        
reverseList([ H | Old], New) :- reverseList(Old, [ H | New]). 

为什么会这样(在swipl中)?

?- useAdd([42, 100, ok], hello).
[ok,100,42,hello]
done []
true.

显然,在New中分配给useAdd相当了,因为正确的列表已传递给reverseList。但是,与New不同,T中的useAdd为空。

  • 这两个作业有何不同?为什么一个起作用而另一个不起作用?
  • 如何在T的{​​{1}}中获取反向列表?

1 个答案:

答案 0 :(得分:1)

您对reverseList/2的定义使用 T作为反向列表的结尾。反向列表是在递归的最深层构建并打印的,然后对创建的值不做任何操作:

2 ?- reverseList( [1,2,3,4], [0]).
[4,3,2,1,0]
true.

相反,将其作为新的逻辑变量传递,作为第三个参数,在调用之间沿原样传递,最后将其设置为最深层次:

reverseList([], List, T) :- List = T, write(List), nl. 
reverseList([H | Old], [], T) :- reverseList(Old, [ H ], T).
reverseList([ H | Old], New, T) :- reverseList(Old, [ H | New], T). 

然后将其称为reverseList( [1,2,3,4], Newtail, T),以将T设置为最深层次的递归:

6 ?- reverseList( [1,2,3,4], [0], T).
[4,3,2,1,0]
T = [4, 3, 2, 1, 0].

定义无处不在,命名很糟糕,并且它可能将T用作“ tail”,因此您应该使用诸如R之类的新参数,至少要暗示一下它会保存 reversed 列表作为调用的 result