<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    Erlang入門(一)

    Posted on 2007-06-13 14:36 dennis 閱讀(29176) 評論(4)  編輯  收藏 所屬分類: erlang
        讀erlang.org上面的Erlang Course四天教程
    1.數字類型,需要注意兩點
    1)B#Val表示以B進制存儲的數字Val,比如
    7> 2#101.
    5
    進制存儲的101就是10進制的5了
    2)$Char表示字符Char的ascii編碼,比如$A表示65

    2.比較難以翻譯的概念——atom,可以理解成常量,它可以包含任何字符,以小寫字母開頭,如果不是以小寫字母開頭或者是字母之外的符號,需要用單引號包括起來,比如abc,'AB'

    3.另一個概念——Tuple,有人翻譯成元組,可以理解成定長數組,是Erlang的基礎數據結構之一:
    8> {1,2,3,4,5}.
    {
    1,2,3,4,5}
    9> {a,b,c,1,2}.
    {a
    ,b,c,1,2}
    10> size({1,2,3,a,b,c}).
    6
    內置函數size求長度,元組可以嵌套元組或者其他結構。下面所講的列表也一樣。

    4.另外一個基礎數據結構就是各個語言都有的list(列表),在[]內以,隔開,可以動態改變大小,
        [123, xyz]
        [
    123, def, abc]
        [{person
    , 'Joe', 'Armstrong'},
            {person
    , 'Robert', 'Virding'},
            {person
    , 'Mike', 'Williams'}
        ]
    可以使用內置函數length求列表大小。以""包含的ascii字母代表一個列表,里面的元素就是這些字母的ascii值,比如"abc"表示列表[97,98,99]。

    5.通過這兩個數據結構可以組合成各種復雜結構,與Lisp的cons、list演化出各種結構一樣的奇妙,Erlang也可以當作是操作列表的語言。

    6.Erlang中變量有兩個特點:
    1)變量必須以大寫字母或者下劃線開頭,可以包含字母、下劃線和@
    2)變量只能綁定一次,也就是所謂的Single Assignment。或者以一般的說法就是只能賦值一次,其實Erlang并沒有賦值這樣的概念,=號也是用于驗證匹配。

    7.模式匹配——Pattern Matching,Erlang的模式匹配非常強大,看了buaawhl的《Erlang語法提要》的介紹,模式匹配的功能不僅僅在課程中介紹的數據結構的拆解,在程序的分派也扮演重要角色,或者說Erlang的控制的流轉是通過模式匹配來實現的。具體功能參見鏈接,給出書中拆解列表的例子:
        [A,B|C] = [1,2,3,4,5,6,7]
            Succeeds 
    - binds A = 1, B = 2,
            C 
    = [3,4,5,6,7]
        
        [H
    |T] = [1,2,3,4]
            Succeeds 
    - binds H = 1, T = [2,3,4]
        
        [H
    |T] = [abc]
            Succeeds 
    - binds H = abc, T = []
        
        [H
    |T] = []
            Fails

    下面會給出更多模式匹配的例子,給出一個模塊用來計算列表等

    8.Erlang中函數的定義必須在一個模塊內(Module),并且模塊和函數的名稱都必須是atom,函數的參數可以是任何的Erlang類型或者數據結構,函數要被調用需要從模塊中導出,函數調用的形式類似:
    moduleName:funcName(Arg1,Arg2,...).
    寫我們的第一個Erlang程序,人見人愛的Hello World:
    -module(helloWorld).
    -export([run/1]).
    run(Name)
    ->
        io
    :format("Hello World ~w~n",[Name]).
    存為helloWorld.erl,在Erlang Shell中執行:
    2> c(helloWorld).
    {ok
    ,helloWorld}
    3> helloWorld:run(dennis).
    Hello World dennis
    ok
    打印出來了,現在解釋下程序構造,
    -module(helloWorld).
    這一行聲明了模塊helloWorld,函數必須定義在模塊內,并且模塊名稱必須與源文件名相同。
    -export([run/1]).
    而這一行聲明導出的函數,run/1指的是有一個參數的run函數,因為Erlang允許定義同名的有不同參數的多個函數,通過指定/1來說明要導出的是哪個函數。
    接下來就是函數定義了:
    run(Name)->
        io
    :format("Hello World ~w~n",[Name]).
    大寫開頭的是變量Name,調用io模塊的format方法輸出,~w可以理解成占位符,將被實際Name取代,~n就是換行了。注意,函數定義完了要以句號.結束。然后執行c(helloWorld).編譯源代碼,執行:
    helloWorld:run(dennis);

    9.內置的常用函數:
        date()
        
    time()
        
    length([1,2,3,4,5])
        size({a
    ,b,c})
        atom_to_list(an_atom)
        list_to_tuple([
    1,2,3,4])
        integer_to_list(
    2234)
        tuple_to_list({})
        hd([1,2,3,4])  %輸出1,也就是列表的head,類似Lisp的car
        tl([1,2,3,4])  %輸出[2,3,4],也就是列表的tail,類似List的cdr

    10.常見Shell命令:
    1)h(). 用來打印最近的20條歷史命令
    2)b(). 查看所有綁定的變量
    3) f(). 取消(遺忘)所有綁定的變量。
    4) f(Val).  取消指定的綁定變量
    5) e(n).   執行第n條歷史命令
    6) e(-1).  執行上一條shell命令

    11.又一個不知道怎么翻譯的概念——Guard。翻譯成約束?呵呵。用于限制變量的類型和范圍,比如:
         number(X)    - X 是數字
        integer(X)    
    - X 是整數
        float(X)    
    - X 是浮點數
        atom(X)        
    - X 是一個atom
        tuple(X)    
    - X 是一個元組
        list(X)        
    - X 是一個列表
        
        
    length(X) == 3    - X 是一個長度為3的列表
        size(X) 
    == 2    - X 是一個長度為2的元組
        
        X 
    > Y + Z    - X >Y+Z
        X 
    == Y        - X 與Y相等
        X 
    =:= Y        - X 全等于Y
        (比如: 
    1 == 1.0 成功
                   
    1 =:= 1.0 失敗)
    為了方便比較,Erlang規定如下的比較順序:
    number < atom < reference < port < pid < tuple < list
    其中pid就是process的id。

    12.忘了介紹apply函數,這個函數對于熟悉javascript的人來說很親切,javascript實現mixin就得靠它,它的調用方式如下:
    apply(Mod, Func, Args),三個參數分別是模塊、函數以及參數列表,比如調用我們的第一個Erlang程序:
    apply(helloWorld,run,[dennis]).
    13.if和case語句,if語句的結構如下:
    if
    Guard1 ->
    Sequence1 ;
    Guard2 ->
    Sequence2 ;
    ...
    end
    而case語句的結構如下:
    case Expr of
    Pattern1 [when Guard1] 
    -> Seq1;
    Pattern2 [when Guard2] 
    -> Seq2;

    PatternN [when GuardN] 
    -> SeqN
    end


    if和case語句都有一個問題,就是當沒有模式匹配或者Grard都是false的時候會導致error,這個問題case可以增加一個類似java中default的:
    case Fn of

       _ 
    ->
       true
    end
    通過_指代任意的Expr,返回true,而if可以這樣:
    if
      

      true 
    ->
       true
    end
    一樣的道理。case語句另一個需要注意的問題就是變量范圍,每個case分支中定義的變量都將默認導出case語句,也就是在case語句結束后可以被引用,因此一個規則就是每個case分支定義的變量應該一致,不然算是非法的,編譯器會給出警告,比如:
    f(X) ->
    case g(X) of
    true 
    -> A = h(X), B = A + 7;
    false 
    -> B = 6
    end
    ,
    h(A)
    .

    如果執行true分支,變量A和變量B都被定義,而如果執行的false分支,只有變量B被定義,可在case語句執行后,h(A)調用了變量A,這是不安全的,因為變量A完全可能沒有被定義,編譯器將給出警告
    variable 'A' unsafe in 'case' (line 10)



    14.給出一些稍微復雜的模型匹配例子,比如用于計算數字列表的和、平均值、長度、查找某元素是否在列表中,我們把這個模塊定義為list:
    -module(list).
    -export([average/1,sum/1,len/1,double/1,member/2]).
    average(X)
    ->sum(X)/len(X).
    sum([H
    |T]) when number(H)->H+sum(T);
    sum([])
    ->0.
    len([_
    |T])->1+len(T);
    len([])
    ->0.
    double([H
    |T]) -> [2*H|double(T)];
    double([]) 
    -> [].
    member(H
    , [H|_]) -> true;
    member(H
    , [_|T]) -> member(H, T);
    member(_
    , []) -> false.
                    

    細細體會,利用遞歸來實現,比較有趣,這其實與Lisp中利用尾遞歸來實現迭代是一樣的道理,[H|T]的形式類似Lisp中的car、cdr操作。_用于指代任意的變量,當我們只關注此處有變量,但并不關心變量的值的時候使用。用分號;來說明是同一個函數定義,只是不同的定義分支,通過模式匹配來決定調用哪個函數定義分支。
    另一個例子,計算各種圖形的面積,也是課程中給出的例子:

    -module(mathStuff).
    -export([factorial/1,area/1]).
    factorial(
    0)->1;
    factorial(N) when N
    >0->N*factorial(N-1).
    %計算正方形面積,參數元組的第一個匹配square    
    area({square
    , Side}) ->
        Side 
    * Side;
    %計算圓的面積,匹配circle  
    area({circle
    , Radius}) ->
       
    % almost :-)
       
    3 * Radius * Radius;
    %計算三角形的面積,利用海倫公式,匹配triangle 
    area({triangle
    , A, B, C}) ->
       S 
    = (A + B + C)/2,
    math
    :sqrt(S*(S-A)*(S-B)*(S-C));
    %其他
    area(Other) 
    ->
       {invalid_object
    , Other}.

    執行一下看看:
    1> c(mathStuff).
    {ok
    ,mathStuff}
    2> mathStuff:area({square,2}).
    4
    3> mathStuff:area({circle,2}).
    12
    4> mathStuff:area({triangle,2,3,4}).
    2.90474
    5> mathStuff:area({other,2,3,4}).
    {invalid_object
    ,{other,2,3,4}}

    Erlang使用%開始單行注釋。

    評論

    # re: Erlang入門(一)[未登錄]  回復  更多評論   

    2007-09-03 16:39 by -274°C
    希望交換鏈接,我最近也在學習Erlang。這方面交流的人還不多。

    # re: Erlang入門(一)  回復  更多評論   

    2007-09-03 16:51 by dennis
    好,有機會交流下學習Erlang,我也在繼續深入,已經添加您的鏈接

    # re: Erlang入門(一)  回復  更多評論   

    2008-12-08 19:59 by Jizhaohui
    本文絕對是入門必讀的.
    非常清晰淺顯,值得入門者一讀!

    # re: Erlang入門(一)  回復  更多評論   

    2009-01-06 17:17 by 新溪
    我現在也在學這個,打算盡快學出個所以然來,弄個網絡五子棋玩玩。
    主站蜘蛛池模板: 小草在线看片免费人成视久网| 国产亚洲日韩在线a不卡| 三年片在线观看免费西瓜视频| 亚洲色一色噜一噜噜噜| 边摸边脱吃奶边高潮视频免费| 午夜亚洲国产成人不卡在线| 亚洲AV成人精品一区二区三区| 日本无卡码免费一区二区三区| 亚洲精品无AMM毛片| 日本高清免费aaaaa大片视频| MM1313亚洲国产精品| 免费大香伊蕉在人线国产| 亚洲AV无码国产一区二区三区| 国产成人无码a区在线观看视频免费| 亚洲熟妇无码AV不卡在线播放| 日韩高清在线免费观看| 免费看一级毛片在线观看精品视频| 亚洲午夜国产片在线观看| baoyu116.永久免费视频| 久久夜色精品国产亚洲| 最近中文字幕免费2019| 亚洲色偷偷色噜噜狠狠99| 四虎永久精品免费观看| 成人一区二区免费视频| 久久亚洲私人国产精品| 两个人的视频高清在线观看免费 | 亚洲av日韩片在线观看| 国产免费AV片在线观看播放| 亚洲av日韩综合一区在线观看| 51在线视频免费观看视频| 亚洲欧美日韩综合久久久| 亚洲国产精品一区二区第一页免| 国产色无码精品视频免费| 一本色道久久88—综合亚洲精品 | 亚洲三级在线免费观看| 99亚洲乱人伦aⅴ精品| 国产亚洲成av片在线观看| 999国内精品永久免费视频| 青青青视频免费观看| 亚洲欧洲尹人香蕉综合| 国产国产成年年人免费看片|