ErLang Map 函数的尾递归形式 / Final List

ErLang Map 函数的尾递归形式

循环语句需要计数器变量控制循环次数,而计数器变量需要多次改变数值。ErLang语言不支持可以重复赋值的变量,因而也不支持循环语句。
ErLang程序员只能用递归表示循环。有些服务程序需要运行在在一个无穷循环中。
while true
listen and respond to user request ….

这种情况下,ErLang程序也要写成无穷递归的形式。在ErLang中,无穷递归必须写成尾递归(Tail Recursion)的形式。因为ErLang是栈语言,如果是非尾递归的递归形式,无穷递归必然引起运行栈的无限膨胀。

下面我们来看一个非尾递归形式转化为尾递归的例子。
ErLang不支持循环语句,而是采用Map、Reduce等便利函数把递归形式简化为类似循环的形式。
map函数的定义为,用一个函数处理一个List中的每一个元素,并且产生每一个结果元素,这些结果元素构成一个新的List,作为返回值。
map函数的调用形式为:

map(
%% 定义一个匿名函数,作为函数体。函数参数就是List中的每一个元素
fun(Item) ->
do something with Item
return a Result Item of processing the Item
end,

List %% 第二个参数List。表示要处理的源List。
)

map函数的具体例子就不多说了。这是比较常见的函数调用。
我们来看map函数的实现。

map(Visit, [] ) -> [] ;
map(Visit, [H | T]) -> [Vsit(H) | map(Visit, T)].

我们看到,上述实现方法里面的递归调用,不是尾递归。
因此运行的过程中,运行栈不断地增长,长到头之后,运行栈再递减。
下面我们把map函数改写成尾递归形式。
由于ErLang的变量都是final的,不能重复赋值。因此我们只能够给List添加一个头,而不能添加尾。所以,我们要在最后把处理结果倒置一下。

map(Visit, L) ->
R = process( Visit, L, [] ),
lists:reverse( R ).

process( Visit, [], R ) -> R;
process( Visit, [H | T], R) ->
RH = Visit( H ),
process(Visit, T, [RH | R]).

我们看到,实际上,我们相当于用一个存放结果的R List代替了运行栈。每一次处理元素的结果都会放入到R这个List当中。
上述代码是尾递归形式,在运行过程,运行栈保持不变。当然,R这个结果List却在不断地增长。相当于自己用一个List代替了运行栈。只不过自己维护的这个List是在堆里面分配的,不受到运行栈大小的限制,只受到内存的限制。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值