在Erlang中进行递归主要考虑三点:1.怎么结束,2.怎么递归,3.怎么开始。只要搞清楚了这三点Erlang递归就不难,这种递归思想在Erlang中的运用非常广泛。
我们通过几道题来看看Erlang的递归
1、找出列表中最后一个元素
lastFun([A|T]) -> lastFun(A,T). %% 怎么开始
lastFun(_,[A|T]) ->lastFun(A,T); %% 怎么递归
lastFun(A,[]) -> A. %% 怎么结束
2、找出列表中第N个元素
nElem(N,[]) -> false;
nElem(1,[A|_T]) -> A; %% 怎么结束
nElem(N,[_|T]) when N>1 ->
nElem(N-1,[T]). %% 怎么递归
3、实现lists:sum()
sum(T) -> sum(T,0). %% 怎么开始
sum([],Acc0) -> Acc0; %% 怎么结束
sum([H|T],Acc0) -> sum(T,Acc0 + H). %% 怎么递归
4、实现lists:reverse
lreverse(List) -> lreverse(List,[]). %% 怎么开始
lreverse([ X|Rest],Acc) ->lreverse(Rest,[X|Acc]); %% 怎么递归
lreverse([],Acc) ->Acc. %% 怎么结束
如上求一个列表中的最后一个元素,怎么结束:我的算法是这样的,既然需要的只是列表的最后一个元素,其他的元素并不需要,那我就把列表写成[A|T],然后通过递归不断的把A扔掉,当T为[]是就可以结束了,并返回A, 即lastFun(A,[]) -> A;怎么递归:如上面的算法所述,我要不断的把列表的第一个元素扔掉,即lastFun(_,[A|T]) ->lastFun(A,T),怎么开始:上面的lastFun函数有两个参数,而一个列表就只有一个参数,所以我们要想办法把列表和函数连接起来,即lastFun([A|T]) -> lastFun(A,T)。又如实现reverse函数的功能,基本的算法如下:我先定义一个空列表,然在将目标列表从第一个元素开始按顺序一个一个加到这个空列表中。怎么结束:当我们把目标列表的元素全部加完的时候就可以结束了,即lreverse([],Acc) ->Acc,怎么递归:如上述算法所述,将目标列表的元素加到空列表中,即lreverse([ X | Rest],Acc) -> lreverse(Rest,[X|Acc]),如何开始:我们要对Acc进行初始化即为[],即lreverse(List) -> lreverse(List,[]).
5、计算一个整数的二进制中有多少个1,例如10的二进制表示为1010,那么输出2.
testfun( Inte ) ->
testfun( Inte ,0, 1). %%怎么开始
tesrfun(Inte,Index,0) ->
Index; %%怎么结束
testfun ( Inte ,Index, N ) ->
if ( Inte band N ) =:= N –>
tesrfun( Inte,Index+1,N bsl 1);
( Inte band N ) =:= 0 ->
tesrfun(Inte,Index,N bsl 1)
end. %% 怎么递归
6、不使用+、-、*、/计算两个整数和
testfun( A , 0 ) -> %%怎么结束
A;
testfun( A , B) ->
testfun( A bxor B ,( A band B) bsl 1). %%怎么递归
最后写一个掉落的例子,这个算法在游戏编程中很常见,大家可以参考一下!
7、20%概率掉落物品A,30%概率掉落物品B,40%概率掉落物品C,10%概率掉落物品D,请实现此随机算法。
testfun() ->
List = [{1,20},{2,40},{3,30},{4,10}],
L = [ Y || {_,Y} <- List ],
N = random:uniform(lists:sum(L)),
F=fun({A,B},{Index,Pacc0,Flag}) ->
if Flag =:= 0 ->
Pacc1 = Pacc0 +B;
if Pacc1 >= N ->
{A,Pacc1,1};
true ->
{Index,Pacc0+B,Flag};
end;
true ->
{Index,Pacc0,Flag}
end,
lists:foldl(F, {0,0,0}, List).
当然也可以用case语句来实现,根据自己的喜好来。