寫 erlang 程式該用函數來思考還是 OO

43 views
Skip to first unread message

Shian

unread,
Mar 9, 2012, 1:44:48 AM3/9/12
to erlang...@googlegroups.com
hi all

erlang 作為一套函數式程式語言提供了許多獨特的特性。一開始學習時就直覺的將要做的工作寫成函式,然後一個接著一個呼叫。在進一步了解到可以將函式本身作為參數,程式的變化與彈性就更大了。但是寫的軟體一大免不了就要用到 OTP ,OTP 是以 process 為單位,彼此之間以訊息溝通,此時 OO 的作法又出現了。

例如,我現在要實做一個 pipe 的系統,也就是定義好每個單元的輸入與輸出,之後可以視需求連接起來執行一項任務。如果以函數式的方式來思考,可以將每個單元寫成函式,一個任務就是:  a(b(c()))  這樣的描述。如果以 OTP 的方式來作,可能每個單元就是一個 gen_server ,然後設定每個單元的上下游串接起來。

我目前是用 OTP 的方式來作這樣的系統,因為 OO 的方式對我來說比較直覺也比較容易解釋給其他人聽,但是相對的程式就比較複雜。大家寫erlang 程式的時候會盡量以函數式的方式思考嗎?

黃耀賢 (Yau-Hsien Huang)

unread,
Mar 10, 2012, 2:07:11 AM3/10/12
to erlang...@googlegroups.com
我覺得在Erlang中, object-oriented programming 和 functional programming 不互斥。

讓我覺得愉快的是只有process算是 instantiatized 的東西,而不是任何各式各樣的資料
全都用物件類別包裹起來。

而thinking in function,我倒覺得不知道如何分別以函數方式思考或不以函數方式思考。
怎樣可稱為不以函數方式思考嗎?或許我可以說,在物件模型中,我無法以較漂亮的
函數方式思考。以前面所提的process來說,很明顯是物件導向,那麼如果以函數導向
思考process呢:例如,

例一:一個函數要接受二個參數可以變成normal form (可評估為一個結果值的情況),
          而假如它只接受一個參數,還可以等待另一個參數而完成。後者這個樣式稱為
          week head normal form。這是目前函數語言學術領域所知到的事實。

例二:一個process要接受二個訊息。當它接受了第一個訊息之後,變成一個本來該
          接受二個訊息以完成工作,但目前只接受一個訊息並仍在等待第二個訊息的
          process。做得到嗎?

像第二個套用到process情況的例子,概念上好像很正常,等實作起來就知道程式寫起來
有多麻煩了,一層又一層的receive-end和case-end。不過其實「等待一個訊息,然後
套用一個函數」這件事情顯然可以抽象為一個單元,像是:

       -export([task/0]).

       wait_for(Msg, Func, Args) ->
            receive
                  { Pid1, Msg } -> {data, apply(Func, Args)}
            after
                  1000 -> {error, "Time Out")
            end.

       continuation([]) ->
            { data, [] };
       continuation( [ { Stage1, Msg1, F, A } | R ] ) ->
            { Case, Data } = wait_for(Msg1, F, A)
            , case Case of
                    data -> case continuation( R ) of
                                   {data, Results} -> {data, [Data|Results]};
                                   {error, Error} -> {error, Error}
                               end;
                    error -> { error , Data ++ " in " ++ Stage1 }
              end.

       task() ->
            case continuation([ {"Stage1", 'hello',  fun do_part_a/1, [a]}
                                        , {"Stage2", 'world', fun do_part_b/2, [b1, b2]}
                                        , ... ]) of
                 { data, Results } -> consult(Results);
                 { error, Error } -> io:format("~w.", [Error])
            end.

這樣子就叫作 object-oriented process programming ,但其中我用continuation代替
普通的 function composition ( f(g(h())) ) 。對照為物件導向程式來看,上面task/1
程式有點像:

       Task t1 = continuation.stage(1, 'hello', jobA, argsA)
                                      .stage(2, 'world', jobB, argsB)
                                      . ... ;
       System.out.println(t1.result());

2012/3/9 Shian <shi...@gmail.com>

--
您已訂閱「Google 網上論壇」的「Erlang_Taiwan」群組,因此我們特別傳送這封郵件通知您。
如要在網路上查看這項討論,請造訪 https://groups.google.com/d/msg/erlang_taiwan/-/YCkEQftmjFsJ
如要在此群組張貼留言,請傳送電子郵件至 erlang...@googlegroups.com
如要取消訂閱此群組,請傳送電子郵件至 erlang_taiwa...@googlegroups.com
如需更多選項,請造訪此群組:http://groups.google.com/group/erlang_taiwan?hl=zh-TW



--

Best Regards.

--- Y-H. H.


Shian Wu

unread,
Mar 11, 2012, 11:50:10 PM3/11/12
to erlang...@googlegroups.com

erlang 寫久了的確是 FP 和 OOP 混在一起 XD
不過這對初學者尤其是從 OOP 過來的人來說,強調 FP 的 erlang 似乎是另一個國度,既然 erlang 中 FP 和 OOP 的成份都有,如果能有一些教學是從 OOP 入手,或許他們會覺得比較舒適點。

例子二可以用 gen_fsm 來作,程式應該看起來清楚一點且可以處理例外狀況。

---
Shian Wu
Reply all
Reply to author
Forward
0 new messages