《Learn You Some Erlang for Great Good!》的学习笔记(六)
来源:互联网 发布:c语言中float什么意思 编辑:程序博客网 时间:2024/05/18 03:06
看到现在你也许会差异,为什么还没有介绍循环语句。作为一个B格很高的语言,erlang并不提供for/while等类似的循环控制关键字,而是使用递归的方式实现循环。递归的话,大家一定不陌生,简单地说就是调用自身函数实现循环,递归的实现有两个要素:
1. 一个基础条件(一般作为结束递归条件)
2. 一个调用自身的函数
以阶乘为例子:
fac(N) when N == 0 -> 1;fac(N) when N > 0 -> N*fac(N-1).
这样就实现了一个递归,我们展开4的阶乘来看一看递归调用的过程:
fac(4) = 4*fac(4-1) = 4*3*fac(3-1) = 4*3*2*fac(2-1) = 4*3*2*1*fac(0) = 4*3*2*1*1
上面就完美了吗?NO!可以发现,当计算4的阶乘时,最大展开了5个参数。数据越大,计算时耗费内存也就越多。该是“尾递归“大显神威的时候啦!
为了避免大量的内存耗费,我们在入参中引入Accumlator作为保存计算结果临时变量,如下所示:
tail_fac(N) -> tail_fac(N,1).tail_fac(0,Acc) -> Acc;tail_fac(N,Acc) when N > 0 -> tail_fac(N-1,N*Acc).
问题就这么解决了?是的,看一下展开效果你就知道了。
tail_fac(4) = tail_fac(4,1)tail_fac(4,1) = tail_fac(4-1, 4*1)tail_fac(3,4) = tail_fac(3-1, 3*4)tail_fac(2,12) = tail_fac(2-1, 2*12)tail_fac(1,24) = tail_fac(1-1, 1*24)tail_fac(0,24) = 24
在内存中至多只保存着两个项目,不会随着数据变化有增多。
由于递归是erlang中实现循环的唯一方式,为了让你能够更加得心应手的使用,这里会给出更多更加复杂的例子。
1.数据复制成数组:
duplicate(N, T) -> duplicate(N, T, []).duplicate(0, _, Acc) -> Acc;duplicate(N, T, Acc) -> duplicate(N - 1, T, [T|Acc]).
2.数组反转
reverse(T) when is_list(T) -> reverse(T, []).reverse([], Acc) -> Acc;reverse([H|T], Acc) -> reverse(T, [H|Acc]).
3.子数组(去数组前N个数据)
sublist(T, N) when is_list(T),length(T) >= N -> sublist(T,N,[]).sublist(T, 0, Acc) -> Acc;sublist([H|T], N, Acc) -> sublist(T, N-1, Acc ++ [H]).
4.相等大小的数组组合(zip)
zip(A1, A2) when is_list(A1), is_list(A2), length(A1)=:=length(A2)-> zip(A1, A2, []).zip([],[], Acc) -> Acc;zip([H1|T1], [H2|T2], Acc) -> zip(T1, T2, Acc++[{H1, H2}]).
5.快速排序
quicksort([]) -> [];quicksort([Pivot|Rest]) -> quicksort([Smaller|| Smaller <- Rest, Smaller =< Pivot]) ++ [Pivot] ++ quicksort([Larger||Larger <- Rest, Larger > Pivot]).
最后,附上作者对递归的理解:
recursion coupled with pattern matching is sometimes an optimal solution to the problem of writing concise algorithms that are easy to understand. By subdividing each part of a problem into separate functions until they can no longer be simplified, the algorithm becomes nothing but assembling a bunch of correct answers coming from short rou- tines (that’s a bit similar to what we did with quicksort). This kind of mental abstraction is also possible with your everyday loops, but I believe the practice is easier with recursion. Your mileage may vary.
- 《Learn You Some Erlang for Great Good!》的学习笔记(六)
- 《Learn You Some Erlang for Great Good!》的学习笔记(一)
- 《Learn You Some Erlang for Great Good!》的学习笔记(二)
- 《Learn You Some Erlang for Great Good!》的学习笔记(三)
- 《Learn You Some Erlang for Great Good!》的学习笔记(四)
- 《Learn You Some Erlang for Great Good!》的学习笔记(五)
- 《Learn You Some Erlang for Great Good!》的学习笔记(七)
- 《Learn You Some Erlang for Great Good!》的学习笔记(八)
- 《Learn You Some Erlang for Great Good!》的学习笔记(九)
- Learn You Some Erlang for Great Good-笔记1-Erlang热代码加载
- here are some very good songs for you learn....
- Some good hyperlink for learn iOS
- some url for learn
- erlang for learn
- Some good URL for iOS
- Erlang学习笔记(六)顺序程序的错误处理
- scikit-learn学习笔记(六)Decision Trees(决策树)
- tensorflow学习笔记(六):TF.contrib.learn大杂烩
- Struts2_17_全局结果集
- require.js的用法
- android6.0 固定屏幕功能
- CodeBlock安装后无法运行为什么?无法找到编译器?
- Scrapy网络爬虫实战[保存为Json文件及存储到mysql数据库]
- 《Learn You Some Erlang for Great Good!》的学习笔记(六)
- 关于android 控件位置控制的几个属性
- 关于弹框加搜索数据功能实现
- 【jzoj4782】【Math】【线性筛法】
- Android 群英传知识点
- angularjs学习一
- openstack dashboard简体中文汉化
- 浅谈MVP模式
- js中获取session中的值(jsp)