1. 程式人生 > >fun函式的強大用法-尾遞迴

fun函式的強大用法-尾遞迴

List Comprehensions的更是強大,官方文件:http://www.erlang.org/doc/programming_examples/list_comprehensions.html



另外列表解析可以在Erlang Shell中方便的實現for迴圈和if

但是在Erlang Shell裡面怎麼寫尾遞迴呢?
1>  Fun =fun(X)  when X rem 2==0 ->X; (X) -> X+1 end .#Fun<erl_eval.6.13229925>
2>  F1 =fun(X)  when X rem 2==0 ->X;
(X) -> (X+1) end .#Fun<erl_eval.6.13229925>
3> F1(5). 6 4> F2 =fun(X) when X rem 2==0 ->X; (X) -> (X+7) end .#Fun<erl_eval.6.13229925> 5> F2(5). 12

可以看到在一個引數的時候,上面的程式碼是可以的,啊哈,不錯,那兩個引數的情況是不是正常呢?
6> F3 = fun(X,Y) when Y<1000 ->io:format("~p,",[X+Y]), (Y,X+Y);
(X,Y)-> done end.* 1: syntax error before: ','

7> F3 = fun(X,Y) when Y<1000 ->io:format("~p,",[X+Y]), (Y,X+Y); (X,Y)-> done end.* 1: syntax error before: ','
8> F1 =fun(X,Y) when X rem 2==0 ->{X,Y}; (X) -> (X+7,Y) end .* 1: syntax error before: ','
7> 結果讓人失望,會有語法錯誤,那沒有引數的情況呢

如果要達到我們的目標,要把尾遞迴要執行的當前方法作為引數傳進去,幾番折騰,終於搞出來了:
8>  F7 = fun(F,X,Y) when Y<1000 ->io:format("~p,",[X+Y]), F(F,Y,X+Y); (F,X,Y)->done end.
#Fun<erl_eval.18.105910772>

馬上寫一個有意義的demo出來看看,輸出一下斐波那契數列吧
1> Func = fun(F, X,Y) when Y<10000 ->io:format("~p,",[X+Y]), F(F,Y,X+Y); (F,X,Y)-> done end.#Fun<erl_eval.18.105910772>
2> Func(Func,0,1).
1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,done
4>
 注意實現尾遞迴呼叫的地方,以及呼叫的方法.


 那麼沒有引數的情況也就水到渠成了:
12>  Fn= fun(F)-> receive {echo,Msg} -> io:format("~p received.~n",[Msg]),F(F);stop-> stop end end.
#Fun<erl_eval.6.13229925>
13> P4=spawn(fun() -> Fn(Fn) end).
<0.48.0>
14> is_process_alive(P4).
true
15> P4!{echo,12}.
12 received.
{echo,12}
16> P4!{echo,hello }.
hello received.
{echo,hello}
17> is_process_alive(P4).
true
18>