• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            教父的告白
            一切都是紙老虎
            posts - 82,  comments - 7,  trackbacks - 0
            ErLang語(yǔ)法中充滿了一些約定。大寫字母開頭的名字(比如Address),表示一個(gè)變量,包括參數(shù)、局部變量等;小寫字母開頭的單詞(比如ok),表示一個(gè)常量,叫做atom(原子的意思),包括常量名、函數(shù)名、模塊名等。

            ErLang的注釋用%開頭。ErLang用下劃線“_”表示任意變量,類似于Java的switch語(yǔ)法里面的default選項(xiàng)。

            ErLang脫胎于Prolog,不過(guò),我覺得,ErLang語(yǔ)法和Haskell語(yǔ)法比較象,都是采用 -> 定義函數(shù)。

            ErLang語(yǔ)句中的標(biāo)點(diǎn)符號(hào)用法很象文章的標(biāo)點(diǎn)符號(hào)。

            整個(gè)函數(shù)定義結(jié)束用一個(gè)句號(hào)“.”;同一個(gè)函數(shù)中,并列的邏輯分支之間,用分號(hào)“;”分界;順序語(yǔ)句之間,用逗號(hào)“,”分隔。

            ErLang中,{ }不是表示程序塊的開頭和結(jié)尾,而是表示一種特殊的數(shù)據(jù)結(jié)構(gòu)類型——Tuple(元組),比如,{12, 3, ok}。我們可以把Tuple理解為定長(zhǎng)數(shù)組。

            [ ] 則表示最基本的函數(shù)式編程的數(shù)據(jù)結(jié)構(gòu)類型——List。List數(shù)據(jù)結(jié)構(gòu)很基本,寫法和用法也有一定的復(fù)雜度,不是表面上看起來(lái)那么簡(jiǎn)單,后面講解Closure的章節(jié)會(huì)詳細(xì)介紹List的最基本的構(gòu)造原理。

            下面我們來(lái)看一個(gè)簡(jiǎn)單的例子。

            我們首先定義一個(gè)最簡(jiǎn)單的函數(shù),把一個(gè)參數(shù)乘以10,然后加1。
            times10( Number ) –>
            Temp = 10 * Number,
            Temp + 1.

            為了說(shuō)明問(wèn)題,上面的代碼把乘法操作和加法操作分成兩個(gè)步驟。Temp = 10 * Number語(yǔ)句后面是逗號(hào),因?yàn)檫@是兩條順序執(zhí)行的語(yǔ)句。Temp + 1語(yǔ)句后面是句號(hào),表示整個(gè)函數(shù)定義結(jié)束。而且,可以看出,ErLang沒有return語(yǔ)句,最后執(zhí)行的那條語(yǔ)句的執(zhí)行結(jié)果就是返回值。

            下面,我們把這個(gè)函數(shù)優(yōu)化一下。當(dāng)參數(shù)等于0的時(shí)候,直接返1;否則,就乘以10,然后加1,然后返回。這時(shí)候,我們就要用到case of邏輯分支語(yǔ)句,相當(dāng)于java的switch語(yǔ)句。

            times10( Number ) –>
            case Number of
            0 -> 1;
            _ ->
            Temp = 10 * Number,
            Temp + 1
            end.

            我們來(lái)仔細(xì)觀察這段ErLang程序。

            當(dāng)Number等于0的時(shí)候,直接返回1。由于這是一條分支語(yǔ)句,和后面的分支是并列的關(guān)系,所以,1的后面的標(biāo)點(diǎn)符號(hào)是分號(hào)。后面這個(gè)分支,下劃線“_”表示任何其它值,這里就表示除了1之外的任何其它數(shù)值。

            需要注意的一點(diǎn)是,case of語(yǔ)句需要用end結(jié)尾,end之前不需要有標(biāo)點(diǎn)符號(hào)。

            上述代碼中的case of 語(yǔ)句,其實(shí)就是Pattern Match的一種。ErLang的Pattern Match很強(qiáng)大,能夠大幅度簡(jiǎn)化程序邏輯,后面進(jìn)行專門介紹。
            Pattern Match
            Pattern Match主要有兩個(gè)功能——比較分派和變量賦值。
            其中,比較分派是最主要的功能。比較分派的意思是,根據(jù)參數(shù)值進(jìn)行條件分支的分派。可以把比較分派功能看作是一種類似于if, else等條件分支語(yǔ)句的簡(jiǎn)潔強(qiáng)大寫法。
            上面的例子中,case Number of 就是根據(jù)Number的值進(jìn)行比較分派。更常見的寫法是,可以把Pattern Match部分提到函數(shù)定義分支的高度。于是,上述代碼可以寫成下面的形式:
            times10( 0 ) –> 1;
            times10( Number ) –>
            Temp = 10 * Number,
            Temp + 1.

            這段代碼由兩個(gè)函數(shù)定義分支構(gòu)成,由于兩個(gè)函數(shù)分支的函數(shù)名相同,而且參數(shù)個(gè)數(shù)相同,而且兩個(gè)函數(shù)定義分支之間采用分號(hào)“;”分隔,說(shuō)明這是同一個(gè)函數(shù)的定義。函數(shù)式編程語(yǔ)言中,這種定義方式很常見,看起來(lái)形式很整齊,宛如數(shù)學(xué)公式。

            這段代碼的含義是,當(dāng)參數(shù)值等于0的時(shí)候,那么,程序走第一個(gè)函數(shù)定義分支(即分號(hào)“;”結(jié)尾的“times10( 0 ) –> 1;”),否則,走下面的函數(shù)定義分支(即“times10( Number ) –>…”)。

            第二個(gè)分支中的參數(shù)不是一個(gè)常數(shù),而是一個(gè)變量Number,表示這個(gè)分支可以接受任何除了0之外的參數(shù)值,比如,1、2、12等等,這些值將賦給變量Number。
            因此,這個(gè)地方也體現(xiàn)了Pattern Match的第二個(gè)功能——變量賦值。

            Pattern Match的形式可以很復(fù)雜,下面舉幾個(gè)典型的例子。
            (1)數(shù)據(jù)結(jié)構(gòu)拆解賦值
            前面將到了ErLang語(yǔ)言有一種相當(dāng)于定長(zhǎng)數(shù)組的Tuple類型,我們可以很方便地根據(jù)元素的位置進(jìn)行并行賦值。比如,
            {First, Second} = {1, 2}
            我們還可以對(duì)復(fù)合Tuple數(shù)據(jù)結(jié)構(gòu)進(jìn)行賦值,比如
            {A, {B, C}, D} = { 1, {2, 3}, 4 }
            List數(shù)據(jù)結(jié)構(gòu)的賦值也是類似。由于List的寫法和用法不是那么簡(jiǎn)單,三言兩語(yǔ)也說(shuō)不清楚,還徒增困擾,這里不再贅述。
            (2)assertEquals語(yǔ)句
            在Java等語(yǔ)言中,我們寫單元測(cè)試的時(shí)候,會(huì)寫一些assert語(yǔ)句,驗(yàn)證程序運(yùn)行結(jié)果。這些assert語(yǔ)句通常是以API的方式提供,比如,assertTrue()、assertEquals()等。
            在ErLang中,可以用簡(jiǎn)單的語(yǔ)句達(dá)到類似于assertTrue()、assertEquals()等API的效果。
            比如,ErLang中,true = testA() 這樣的語(yǔ)句表示testA的返回結(jié)果必須是true,否則就會(huì)拋出異常。這個(gè)用法很巧妙。這里解釋一下。
            前面講過(guò),ErLang語(yǔ)法約定,小寫字母開頭的名字,都是常量名。這里的true自然也是一個(gè)常量,既然是常量,我們不可能對(duì)它賦值,那么true = testA()的意思就不是賦值,而是進(jìn)行匹配比較。
            (3)匹配和賦值同時(shí)進(jìn)行
            我們來(lái)看這樣一段代碼。
            case Result of
            {ok, Message} -> save(Message);
            {error, ErrorMessage} -> log(ErrorMessage)
            end.

            這段代碼中,Result是一個(gè)Tuple類型,包含兩個(gè)元素,第一個(gè)元素表示成功(ok)或者失敗(error),第二個(gè)元素表示具體的信息。
            可以看到,這兩個(gè)條件分支中,同時(shí)出現(xiàn)了常量和變量。第一個(gè)條件分支中的ok是常量,Message是變量;第二個(gè)條件分支中的error是常量,ErrorMessage是變量。
            這兩個(gè)條件分支都既有比較判斷,也有變量賦值。首先,判斷ResultTuple中的第一個(gè)元素和哪一個(gè)分支的第一個(gè)元素匹配,如果相配,那么把ResultTuple中的第二個(gè)元素賦給這個(gè)分支的第二個(gè)變量元素。即,如果Result的第一個(gè)元素是ok,那么走第一個(gè)條件分支,并且把Result的第二個(gè)元素賦給Message變量;如果Result的第二個(gè)元素是error,那么走第二個(gè)條件分支,并且把Result的第二個(gè)元素賦給ErrorMessage變量。

            在Java等語(yǔ)言中,實(shí)現(xiàn)上述的條件分支邏輯,則需要多寫幾條語(yǔ)句ErLang語(yǔ)法可以從形式上美化和簡(jiǎn)化邏輯分支分派復(fù)雜的程序。
            除了支持?jǐn)?shù)相等比較,Pattern Match還可以進(jìn)行范圍比較、大小比較等,需要用到關(guān)鍵字when,不過(guò)用到when的情況,就比if else簡(jiǎn)潔不了多少,這里不再贅述。
            匿名函數(shù)
            ErLang允許在一個(gè)函數(shù)體內(nèi)部定義另一個(gè)匿名函數(shù),這是函數(shù)式編程的最基本的功能。這樣,函數(shù)式語(yǔ)言才可以支持Closure。我們來(lái)看一個(gè)ErLang的匿名函數(shù)的例子。
            outer( C ) –>
            Inner = fun(A, B) -> A + B + C end,
            Inner(2, 3).

            這段代碼首先定義了一個(gè)命名函數(shù)outer,然后在outer函數(shù)內(nèi)部定義了一個(gè)匿名函數(shù)。可以看到,這個(gè)匿名函數(shù)采用關(guān)鍵字fun來(lái)定義。前面講過(guò),函數(shù)式編程的函數(shù)就相當(dāng)于面向?qū)ο缶幊痰念悓?shí)例對(duì)象,匿名函數(shù)自然也是這樣,也相當(dāng)于類實(shí)例,我們可以把這個(gè)匿名函數(shù)賦給一個(gè)變量Inner,然后我們還可以把這個(gè)變量當(dāng)作函數(shù)來(lái)調(diào)用,比如,Inner(2, 3)。
            fun是ErLang用來(lái)定義匿名函數(shù)的關(guān)鍵字。這個(gè)關(guān)鍵字很重要。fun定義匿名函數(shù)的用法不是很復(fù)雜,和命名函數(shù)定義類似。
            函數(shù)分支的定義也是類似,只是需要用end結(jié)尾,而不是用句號(hào)“.”結(jié)尾,而且fun只需要寫一次,不需要向命名函數(shù)那樣,每個(gè)分支都要寫。比如,
            MyFunction = fun(0) -> 0;
            (Number) -> Number * 10 + 1 end,
            MyFunction(3),
            函數(shù)作為變量
            匿名函數(shù)可以當(dāng)作對(duì)象賦給變量,命名函數(shù)同樣也可以賦給變量。具體用法還是需要借助重要的fun關(guān)鍵字。比如,
            MyFunction = fun outer / 1

            就可以把上述定義的outer函數(shù)賦給MyFunction變量。后面的 / 0表示這個(gè)outer函數(shù)只有一個(gè)參數(shù)。因?yàn)镋rLang允許有多個(gè)同名函數(shù)的定義,只要參數(shù)個(gè)數(shù)不同,就是不同的函數(shù)。
            我們可以看到,任何函數(shù)都可以作為變量,也可以作為參數(shù)和返回值傳來(lái)傳去,這些變量也可以隨時(shí)作為函數(shù)進(jìn)行調(diào)用,于是就具有了一定的動(dòng)態(tài)性。
            函數(shù)的動(dòng)態(tài)調(diào)用
            ErLang有一個(gè)apply函數(shù),可以動(dòng)態(tài)調(diào)用某一個(gè)函數(shù)變量。
            基本用法是 apply( 函數(shù)變量,函數(shù)參數(shù)列表 )。比如,上面的MyFunciton函數(shù)變量,就可以這么調(diào)用,apply( MyFunction, [ 5 ])。
            那么我們能否根據(jù)一個(gè)字符串作為函數(shù)名獲取一個(gè)函數(shù)變量呢?這樣我們就可以根據(jù)一個(gè)字符串來(lái)動(dòng)態(tài)調(diào)用某個(gè)函數(shù)了。
            ErLang中,做到這一點(diǎn)很簡(jiǎn)單。前面講過(guò),函數(shù)名一旦定義了,自然就固定了,這也類似于常量名,屬于不可變的atom(原子)。所有的atom都可以轉(zhuǎn)換成字符串,也可以從字符串轉(zhuǎn)換過(guò)來(lái)。ErLang中的字符串實(shí)質(zhì)上都是List。字符串和atom之間的轉(zhuǎn)換通過(guò)list_to_atom和atom_to_list來(lái)轉(zhuǎn)換。
            于是我們可以這樣獲取MyFunciton:MyFunction = list_to_atom(“outer”)
            如果outer函數(shù)已經(jīng)定義,那么MyFucntion就等于outer函數(shù),如果outer函數(shù)沒有定義,那么list_to_atom(“outer”)會(huì)產(chǎn)生一個(gè)新的叫做outer的atom,MyFucntion就等于這個(gè)新產(chǎn)生的atom。
            如果需要強(qiáng)制產(chǎn)生一個(gè)已經(jīng)存在的atom,那么我們需要調(diào)用list_to_existing_atom轉(zhuǎn)換函數(shù),這個(gè)函數(shù)不會(huì)產(chǎn)生新的atom,而是返回一個(gè)已經(jīng)存在了的atom。
            Tuple作為數(shù)據(jù)成員集合
            前面講解函數(shù)式編程特性的時(shí)候,提到了函數(shù)式編程沒有面向?qū)ο缶幊痰某蓡T變量,這是一個(gè)限制。
            ErLang的Tuple類型可以一定程度克服這個(gè)限制。Tuple可以一定程度上擔(dān)當(dāng)容納成員變量的職責(zé)。
            面向?qū)ο蟮念惗x,其實(shí)就是一群數(shù)據(jù)和函數(shù)的集合,只是集合的成員之間都有一個(gè)this指針相關(guān)聯(lián),可以相互找到。
            ErLang的Tuple類型就是數(shù)據(jù)的集合,可以很自然地發(fā)揮成員變量的作用,比如,{Member1, Member2}。
            讀者可能會(huì)說(shuō),ErLang的函數(shù)也可以作為變量,也可以放到Tuple里面,比如, { Memer1, Member2, Funtion1, Function2}。這不就和面向?qū)ο缶幊桃粯恿藛幔?
            遺憾的是,這樣做是得不償失的。因?yàn)楹瘮?shù)式編程沒有面向?qū)ο蟮哪欠N內(nèi)在的this指針支持,自然也沒有內(nèi)在的多態(tài)和繼承支持,硬把數(shù)據(jù)和函數(shù)糅合在一個(gè)Tuple里面,一點(diǎn)好處都沒有,而且還喪失了函數(shù)作為實(shí)例對(duì)象的靈活性。
            所以,函數(shù)式編程的最佳實(shí)踐(Best Practice)應(yīng)該是:Tuple用來(lái)容納成員數(shù)據(jù),函數(shù)操作Tuple。Tuple定義和函數(shù)定義加在一起,就構(gòu)成了松散的數(shù)據(jù)結(jié)構(gòu),功能上類似于面向?qū)ο蟮念惗x。Tuple + 函數(shù)的數(shù)據(jù)結(jié)構(gòu),具有多態(tài)的特性,因?yàn)楹瘮?shù)本身能夠作為變量替換;但是不具有繼承的特性,因?yàn)闆]有this指針的內(nèi)在支持。
            正是因?yàn)門uple在數(shù)據(jù)類型構(gòu)造方面的重大作用,所以,ErLang專門引入了一種叫做Record的宏定義,可以對(duì)Tuple的數(shù)組下標(biāo)位置命名。比如,把第一個(gè)元素叫做Address,第二個(gè)元素叫做Zipcode,這樣程序員就可以這些名字訪問(wèn)Tuple里面的元素,而不需要按照數(shù)組下標(biāo)位置來(lái)訪問(wèn)。
            Tuple和Record的具體用法還是有一定復(fù)雜度,限于篇幅,本章沒有展開說(shuō)明,只提了一些原理方面的要點(diǎn)。
            其它
            ErLang還有其它語(yǔ)法特性和細(xì)節(jié),不再一一贅述。有興趣的讀者,可以自行去ErLang網(wǎng)站(www.erlang.org)進(jìn)行研究。
            posted on 2009-09-11 11:04 暗夜教父 閱讀(733) 評(píng)論(0)  編輯 收藏 引用 所屬分類: erlang

            <2009年9月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            常用鏈接

            留言簿(2)

            隨筆分類

            隨筆檔案

            文章分類

            文章檔案

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久婷婷色香五月综合激情| 亚洲国产精品无码久久久久久曰| AV色综合久久天堂AV色综合在| 久久国产香蕉一区精品| 国产精品xxxx国产喷水亚洲国产精品无码久久一区| 久久人人爽人人人人片av| 久久久久久久久久久久久久| 中文字幕热久久久久久久| 久久人人爽人人爽人人AV东京热| 国内精品久久久久久野外| 久久精品国产亚洲一区二区三区| 欧洲国产伦久久久久久久| 精品免费久久久久久久| 国产精品热久久毛片| 国产精品99久久久久久宅男小说| 国产农村妇女毛片精品久久| 亚洲国产日韩综合久久精品| 狠狠色丁香婷婷久久综合不卡| 久久一区二区免费播放| 久久se精品一区精品二区| 日韩欧美亚洲综合久久影院Ds| 日本欧美久久久久免费播放网 | 久久精品这里只有精99品| 99精品国产综合久久久久五月天 | 伊人久久大香线蕉亚洲| 色偷偷久久一区二区三区| 亚洲嫩草影院久久精品| 成人久久综合网| 丰满少妇高潮惨叫久久久| 香蕉久久AⅤ一区二区三区| 99久久www免费人成精品| 亚洲中文字幕久久精品无码喷水| 久久国产一片免费观看| segui久久国产精品| 久久综合日本熟妇| 青青草原综合久久大伊人| 亚洲中文字幕无码久久2020| 国产色综合久久无码有码| 久久婷婷色综合一区二区| 久久精品国产福利国产琪琪| 久久精品国产精品亚洲|