本篇介紹如何使用erlang來達到java, javascript的for的寫法
首先先寫幾行簡單的程式碼,接著再示範如何重覆的執行這些程式碼, 程式碼如下。
connect()->
{ok,S} = gen_tcp:connect({127,0,0,1},2222,[{packet,2}]), (1)
Result = gen_tcp:send(S,<<"hello">>), (2)
Result.
(1)使用tcp連線到server的2222 port
(2)送hello字串到server
如果我們要將connect()執行100次的話該如何寫? 由於erlang沒有內建的for可以使用,所以我們只能用遞迴(recursive)的寫法,如下
run()->
T = 100,
connect(T),
ok.
connect(T)->
if
T>0->
{ok,S} = gen_tcp:connect({127,0,0,1},2222,[{packet,2}]), (1)
gen_tcp:send(S,<<"hello">>), (2)
connect(T-1);
true->
ok
end.
先改寫connect function,在該function增加一個參數叫T(執行次數),如果T>0的話就執行(1)連線至tcp server (2)送hello字串至server,接著將T-1後繼續呼叫connect function,如果T=0的話就結束,不再遞迴呼叫
增加run function,在該function定義T來儲存要執行100次,接著就使用使參數來呼叫connect function。
上述寫法會有一個缺點,connection function的邏輯應該專注在執行連線、送資料部份,但現在裡面多加了與邏輯無關的程式流程控制在裡面,我們來看下列改良的寫法
run()->
R = for(1, 100, fun connect/1), (1)
io:format("R=~p~n", [R]),
ok.
connect(I)->
{ok,S} = gen_tcp:connect({127,0,0,1},2222,[{packet,2}]),
Result = gen_tcp:send(S,<<"hello">>),
{I,Result}.
for(Max, Max, F) -> [F(Max)]; (2)
for(I, Max, F) -> [F(I)|for(I+1, Max, F)]. (3)
此寫法增加了for/3 function來控制程式要執行幾次,connect function僅專注在連線、送資料。
首先來看(2)(3) for function的部份,該function有3個參數,第1個參數是起始值,第2個參數是結束值,第3個參數是所要執行的function,也就是connection/1
接著我們來看(1) for(1, 100, fun connect/1),這有點像我們一般習慣的for寫法,也就是描述要執行connect/1 100次。
首先會先呼叫到for(I, Max, F),所以會先執行F(I)也就是connect(1),接著再把I+1後呼叫for(I+1, Max, F)也就是for(2, 100, F)。最終執行到for(100,100,F)。
整個執行過程會像下列...最終會回傳一個list存著每個connection function的回傳值 [connect(1), connection(2), connection(3).....connect(100)]
另外erlang有提供foreach的function,該function適用時機在List值已知,將再List裡的值一個一個傳給function去執行,範例如下
test_foreach()->
lists:foreach(fun connect2/1, ["hello", "how", "are", "you"]).
connect2(Text)->
{ok,S} = gen_tcp:connect({127,0,0,1},2222,[{packet,2}]),
gen_tcp:send(S,term_to_binary(Text)).
上述的例子總共會執行4次connect2,代入的connection2參數依次為"hello", "how", "are", "you"
小結
在java裡用到遞迴的機會不多,或許可以用其它的寫法躲過遞迴,但踏入erlang後遞迴是閃不掉的,還是得花時間適應。
沒有留言:
張貼留言