首页 > 解决方案 > 递归变量赋值

问题描述

鉴于这种:

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.

显然分配到NewinuseAdd相当于一些东西,因为正确的列表被传递给reverseList. 但是,与 不同的是NewTinuseAdd是空的。

标签: prolog

解决方案


您将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可能用于“尾巴”,所以你应该将新参数命名为类似的名称R,至少暗示它将保存反向列表作为结果的调用。


推荐阅读