Windows環(huán)境下安裝Erlang
??在http://www.erlang.org/downloads下載安裝了Erlang之后处硬,再配置path系統(tǒng)變量Erlang安裝目錄/bin
手报。之后在cmd命令行中,輸入erl命令,即可進(jìn)入Erlang shell環(huán)境频轿。
基本概念
注釋
??Erlang里的注釋從一個(gè)百分號(hào)字符(%)開(kāi)始饥侵,一直延伸到行尾。Erlang沒(méi)有塊注釋哩簿。
??根據(jù)規(guī)范宵蕉,與代碼同處一行的注釋以一個(gè)%開(kāi)頭酝静,獨(dú)占一行的注釋以兩個(gè)%%開(kāi)頭。
整數(shù)和浮點(diǎn)數(shù)
??整數(shù)無(wú)大小限制羡玛,$符號(hào)加字符可以得到字符的編碼數(shù)值别智,比如$a,可以得到a的編碼數(shù)值稼稿。
??在Erlang里浮點(diǎn)數(shù)都是雙精度浮點(diǎn)數(shù)薄榛。
運(yùn)算符
??有兩種除法運(yùn)算,使用/
運(yùn)算符返回浮點(diǎn)數(shù)让歼,div
運(yùn)算符返回整數(shù)敞恋,rem
運(yùn)算符是求余,也可以使用math模塊的運(yùn)算函數(shù)谋右。
??任何類型之間都可以使用比較運(yùn)算符進(jìn)行比較硬猫,數(shù)值小于原子,元組小于列表倚评,而原子既小于元組也小于列表浦徊。
??小于或等于運(yùn)算符寫(xiě)作=<
,大于或等于運(yùn)算符寫(xiě)作>=
天梧。
??=:=
是完全相等運(yùn)算符(值和類型都相同)盔性,=/=
是不完全相等運(yùn)算符。如果想執(zhí)行不考慮類型的比較呢岗,比如比較2和2.0冕香,則需要使用==
運(yùn)算符,其否定形式是/=
后豫。
位串
??<< >>內(nèi)用逗號(hào)分隔整數(shù)序列悉尾,整數(shù)取值范圍是0~255,也可以使用字符串代替整數(shù)挫酿。
變量和符號(hào)常量
??Erlang是一種函數(shù)式語(yǔ)言构眯,所以一旦定義了X = 123
,那么X永遠(yuǎn)就是123早龟,不允許改變惫霸。如果再執(zhí)行X = abc
,則會(huì)拋錯(cuò)葱弟,當(dāng)可以重復(fù)執(zhí)行X = 123
壹店。等號(hào)只是模式匹配,而不是賦值操作芝加,通過(guò)以下觀察最后例子123=X
和12=X
硅卢,可以明白一些,這種機(jī)制有點(diǎn)類似于==操作,可以用來(lái)做測(cè)試使用将塑。
1> X=123.
123
2> X=abc.
** exception error: no match of right hand side value abc
3> X=123.
123
4> Y=123.
123
5> X=Y.
123
6> K=abc.
abc
7> X=K.
** exception error: no match of right hand side value abc
8> 123=X.
123
9> 12=X.
** exception error: no match of right hand side value 123
??沒(méi)有可變變量將如何編程脉顿?在Erlang里怎樣表達(dá)X = X + 1這類概念?Erlang的方式是創(chuàng)建一個(gè)名字未被使用過(guò)的新變量(比方說(shuō)X1)抬旺,然后編寫(xiě)X1 = X + 1弊予。
??請(qǐng)注意Erlang的變量以大寫(xiě)字母開(kāi)頭。所以X开财、This和A_long_name都是變量汉柒。以小寫(xiě)字母開(kāi)頭的名稱(比如monday或friday)不是變量,而是符號(hào)常量责鳍,它們被稱為原子(atom)碾褂。
原子
??在Erlang里,原子被用于表示常量值历葛。原子以小寫(xiě)字母開(kāi)頭正塌,后接一串字母、數(shù)字恤溶、下劃線(_)或at(@)符號(hào)乓诽。
??原子還可以放在單引號(hào)(')內(nèi)≈涑蹋可以用這種引號(hào)形式創(chuàng)建以大寫(xiě)字母開(kāi)頭(否則會(huì)被解釋成變量)或包含字母數(shù)字以外字符的原子鸠天,例如'Monday'、'Tuesday'帐姻、'+'稠集、'*'和'an atom with spaces'。
??true和false這兩個(gè)原子可以用于布爾運(yùn)算饥瓷。undefined表示未知量的占用符剥纷。
元組
??元組把一些數(shù)量固定的項(xiàng)目歸組成單一的實(shí)體,元祖這樣定義:P = {joe, 1.82}
呢铆。
??在Erlang中晦鞋,=不是賦值語(yǔ)句,而是模式匹配操作符棺克。如果想要提取P = {joe, 1.82}
里面的1.82這個(gè)值鳖宾,需要執(zhí)行{joe,X}=P
,這樣1.82這個(gè)值就會(huì)賦給變量X逆航。
列表
??列表(list)被用來(lái)存放任意數(shù)量的事物。創(chuàng)建列表的方法是用中括號(hào)把列表元素括起來(lái)渔肩,并用逗號(hào)分隔它們因俐。
??列表的第一個(gè)元素被稱為列表頭(head),假設(shè)把列表頭去掉,剩下的就被稱為列表尾(tail)抹剩。訪問(wèn)列表頭是一種非常高效的操作撑帖。
??可以給列表T的開(kāi)頭添加不止一個(gè)元素,寫(xiě)法是[E1,E2,..,En|T]
澳眷。
??和其他情況一樣胡嘿,我們可以用模式匹配操作來(lái)提取某個(gè)列表里的元素。如果有一個(gè)非空列表L钳踊,那么表達(dá)式[X|Y] = L
(X和Y都是未綁定變量)會(huì)提取列表頭作為X衷敌,列表尾作為Y。
字符串
??嚴(yán)格來(lái)說(shuō)拓瞪,Erlang里沒(méi)有字符串缴罗。Name="Hello"
,Hello
其實(shí)只是一個(gè)列表的簡(jiǎn)寫(xiě)祭埂,這個(gè)列表包含了代表字符串里各個(gè)字符的整數(shù)字符代碼面氓。
??當(dāng)shell打印某個(gè)列表的值時(shí),如果列表內(nèi)的所有整數(shù)都代表可打印字符蛆橡,它就會(huì)將其打印成字符串字面量舌界。否則,打印成列表記法泰演。不需要知道代表某個(gè)字符的是哪一個(gè)整數(shù)呻拌,可以把“美元符號(hào)語(yǔ)法”用于這個(gè)目的
1> [1,2,3].
[1,2,3]
2> [83,117,114,112,114,105,115,101].
"Surprise"
3> [$S,$u,$r,$p,$r,$i,$s,$e].
"Surprise"
模式匹配
模式 = 單元 結(jié) 果
{X,abc} = {123,abc} 成功:X = 123
{X,Y,Z} = {222,def,"cat"} 成功:X = 222,Y = def粥血,Z = "cat"
{X,Y} = {333,ghi,"cat"} 失敯爻:元組的形狀不同
X = true 成功:X = true
{X,Y,X} = {{abc,12},42,{abc,12}} 成功:X = {abc,12},Y = 42
{X,Y,X} = {{abc,12},42,true} 失敻纯鳌:X不能既是{abc,12}又是true
[H|T] = [1,2,3,4,5] 成功:H = 1趾娃,T = [2,3,4,5]
[H|T] = "cat" 成功:H = 99,T = "at"
[A,B,C|T] = [a,b,c,d,e,f] 成功:A = a缔御,B = b抬闷,C = c,T = [d,e,f]
模塊和函數(shù)
模塊
??模塊是Erlang的基本代碼單元耕突。模塊保存在擴(kuò)展名為.erl的文件里笤成,而且必須先編譯才能運(yùn)行模塊里的代碼。編譯后的模塊以.beam作為擴(kuò)展名眷茁。
??創(chuàng)建模塊文件炕泳,文件名是name.erl。
-module(name)
-export([FuncName1/N1,FuncName2/N2,...])
??-module(name)
表明此文件是哪個(gè)模塊上祈,name
是文件名(除掉erl后綴)培遵。-export([FuncName1/N1,FuncName2/N2,...])
指明了模塊里哪些函數(shù)可以從模塊外部進(jìn)行調(diào)用浙芙,斜杠后面的N是數(shù)字,表示函數(shù)有多少個(gè)參數(shù)籽腕。未從模塊里導(dǎo)出的函數(shù)只能在模塊內(nèi)調(diào)用嗡呼。
函數(shù)
??Erlang是一種函數(shù)式編程語(yǔ)言。函數(shù)式編程語(yǔ)言表示函數(shù)可以被用作其他函數(shù)的參數(shù)皇耗,也可以返回函數(shù)南窗。操作其他函數(shù)的函數(shù)被稱為高階函數(shù)(higher-order function),而在Erlang中用于代表函數(shù)的數(shù)據(jù)類型被稱為fun郎楼。
-module(my_module).
-export([pie/0]).
pie() ->
3.14.
??以-
開(kāi)頭的語(yǔ)句屬于聲明万伤,-module
聲明指定了模塊的名字,必須和文件名一致箭启。-export
聲明指定了模塊內(nèi)哪些函數(shù)是外部可以調(diào)用的壕翩,pie/0
后面的0的函數(shù)參數(shù)數(shù)量。
??pie() -> 3.14.
是函數(shù)定義傅寡,函數(shù)首部(函數(shù)名和參數(shù)列表)和函數(shù)體使用->
分隔放妈,函數(shù)的返回值不需要return關(guān)鍵字,返回值就是函數(shù)體中表達(dá)式的值荐操,但要注意函數(shù)定義的末尾必須加上句號(hào).
芜抒。
-module(geometry).
-export([area/1]).
area({rectangle,Width,Height}) -> Width*Height;#第一個(gè)子句
area({squre,Side}) -> Side*Side.#第二個(gè)字句
??area函數(shù)有兩個(gè)子句。這些子句由一個(gè)分號(hào)隔開(kāi)托启,最后的子句以句號(hào)加空白結(jié)束宅倒。每條子句都有一個(gè)頭部和一個(gè)主體,兩者用箭頭(->)分隔屯耸。頭部包含一個(gè)函數(shù)名拐迁,后接零個(gè)或更多個(gè)模式,主體則包含一列表達(dá)式疗绣,它們會(huì)在頭部里的模式與調(diào)用參數(shù)成功匹配時(shí)執(zhí)行线召。這些子句會(huì)根據(jù)它們?cè)诤瘮?shù)定義里出現(xiàn)的順序進(jìn)行匹配。
1> c(geometry).
{ok,geometry}
2> geormetry:area({rectangle,10,5}).
50
3> geormetry:area({square,3}).
9
內(nèi)置函數(shù)和標(biāo)準(zhǔn)庫(kù)
??erlang模塊
包含了整個(gè)Erlang系統(tǒng)最核心的函數(shù)多矮,io模塊
處理文本輸入輸出缓淹,dict模塊
提供了基于散列的關(guān)聯(lián)數(shù)組(字典),array模塊
提供了可擴(kuò)展的塔逃、帶整數(shù)索引的數(shù)組讯壶。erlang模塊中的有些函數(shù)會(huì)被自動(dòng)導(dǎo)入,比如self()
函數(shù)其實(shí)erlang:self()
湾盗,因?yàn)樗呀?jīng)被自動(dòng)導(dǎo)入伏蚊,所以可以省略erlang:
。
標(biāo)點(diǎn)符號(hào)使用
- 逗號(hào)(,)分隔函數(shù)調(diào)用格粪、數(shù)據(jù)構(gòu)造和模式中的參數(shù)
- 分號(hào)(;)分隔子句丙挽。我們能在很多地方看到子句肺孵,例如函數(shù)定義,以及case颜阐、if、try..catch和receive表達(dá)式
- 句號(hào)(.)(后接空白)分隔函數(shù)整體吓肋,以及shell里的表達(dá)式
??有一種簡(jiǎn)單的方法可以記住這些:想想英語(yǔ)凳怨。句號(hào)分隔句子,分號(hào)分隔子句是鬼,逗號(hào)則分隔下級(jí)子句肤舞。逗號(hào)象征短程,分號(hào)象征中程均蜜,句號(hào)則象征長(zhǎng)程李剖。
編譯
??在erl文件目錄下進(jìn)入shell,執(zhí)行c(模塊名)
即可對(duì)模塊名.erl
進(jìn)行編譯囤耳,編譯完成后會(huì)產(chǎn)生.beam
文件篙顺,之后在shell里就可以通過(guò)模塊名:方法名()
調(diào)用模塊里的函數(shù)。
??在Erlang里有一些用在Shell的函數(shù)充择,格式是name(args)德玫。
case表達(dá)式
case Expression of
Pattern1 [when Guard1] -> Expr_seq1;
Pattern2 [when Guard2] -> Expr_seq2;
...
end
??case的執(zhí)行過(guò)程如下:首先,Expression被執(zhí)行椎麦,假設(shè)它的值為Value宰僧。隨后,Value輪流與Pattern1(帶有可選的關(guān)卡Guard1)观挎、Pattern2等模式進(jìn)行匹配琴儿,直到匹配成功。一旦發(fā)現(xiàn)匹配嘁捷,相應(yīng)的表達(dá)式序列就會(huì)執(zhí)行造成,而表達(dá)式序列執(zhí)行的結(jié)果就是case表達(dá)式的值。如果所有模式都不匹配普气,就會(huì)發(fā)生異常錯(cuò)誤(exception)谜疤。
if表達(dá)式
if
Guard1 ->
Expr_seq1;
Guard2 ->
Expr_seq2;
...
end
??它的執(zhí)行過(guò)程如下:首先執(zhí)行Guard1。如果得到的值為true现诀,那么if的值就是執(zhí)行表達(dá)式序列Expr_seq1所得到的值夷磕。如果Guard1不成功,就會(huì)執(zhí)行Guard2仔沿,以此類推坐桩,直到某個(gè)關(guān)卡成功為止。if表達(dá)式必須至少有一個(gè)關(guān)卡的執(zhí)行結(jié)果為true封锉,否則就會(huì)發(fā)生異常錯(cuò)誤绵跷。
記錄與映射組
記錄
??對(duì)于小型元組而言膘螟,記住各個(gè)元素代表什么幾乎不成問(wèn)題,但當(dāng)元組包含大量元素時(shí)碾局,給各個(gè)元素命名就更方便了荆残。一旦命名了這些元素,就可以通過(guò)名稱來(lái)指向它們净当,而不必記住它們?cè)谠M里的具體位置内斯。記錄其實(shí)就是元組。
-record(Name,{
%%以下兩個(gè)鍵帶有默認(rèn)值
key1=Default1,
key2=Default2,
...
%%下一行就相當(dāng)于key3=undefined
key3,
...
}
??在之前的例子里像啼,Name是記錄名俘闯。key1、key2這些是記錄所含各個(gè)字段的名稱忽冻,它們必須是原子真朗。記錄里的每個(gè)字段都可以帶一個(gè)默認(rèn)值,如果創(chuàng)建記錄時(shí)沒(méi)有指定某個(gè)字段的值僧诚,就會(huì)使用默認(rèn)值遮婶。
??記錄的定義既可以保存在Erlang源代碼文件里,也可以由擴(kuò)展名為.hrl
的文件保存振诬,然后包含在Erlang源代碼文件里蹭睡。
-record{todo,{status=reminder,who=joe,text}}.
%% 創(chuàng)建記錄
1> X1 = #todo{status=urgent,text="Fix errate in book"}.
2> X2 = X1#todo{status=done}.
%% 提取記錄
3> #todo{who=W,text=Txt}=X2.
4> W.
5> Txt.
6> X2%todo.text.
映射組:關(guān)聯(lián)式鍵-值存儲(chǔ)
#{ Key1 Op Val1,Key2 Op Val2,...KeyN Op ValN }
NewMap = OldMap#{ Key1 Op Val1,...KeyN Op ValN }
??Op是=>或:=這兩個(gè)符號(hào)的其中一個(gè)。
??表達(dá)式K => V
有兩種用途赶么,一種是將現(xiàn)有鍵K的值更新為新值V肩豁,另一種是給映射組添加一個(gè)全新的K-V對(duì)。這個(gè)操作總是成功的辫呻。
??表達(dá)式K := V
的作用是將現(xiàn)有鍵K的值更新為新值V清钥。如果被更新的映射組不包含鍵K,這個(gè)操作就會(huì)失敗放闺。
??鍵和值可以是任何有效的Erlang數(shù)據(jù)類型祟昭。
異常處理
??Erlang有兩種方法來(lái)捕捉異常錯(cuò)誤。第一種是把拋出異常錯(cuò)誤的調(diào)用函數(shù)封裝在一個(gè)try...catch表達(dá)式里怖侦,另一種是把調(diào)用封裝在一個(gè)catch表達(dá)式里篡悟。
try FucOrExpressionSeq of
Pattern1 [when Guard1] -> Expression1;
Pattern2 [when Guard2] -> Expression2;
...
catch
ExceptionType1: ExPattern1 [when Guard1] -> ExExpression1;
ExceptionType2: ExPattern2 [when Guard2] -> ExExpression2;
...
after
AfterExpressions
end
??try...catch就像是case表達(dá)式的強(qiáng)化版。它基本上就是case表達(dá)式加上最后的catch和after區(qū)塊匾寝。
??try...catch的工作方式如下:首先執(zhí)行FuncOrExpessionSeq搬葬。如果執(zhí)行過(guò)程沒(méi)有拋出異常錯(cuò)誤,那么函數(shù)的返回值就會(huì)與Pattern1(以及可選的關(guān)卡Guard1)艳悔、Pattern2等模式進(jìn)行匹配急凰,直到匹配成功。如果能匹配猜年,那么整個(gè)try...catch的值就通過(guò)執(zhí)行匹配模式之后的表達(dá)式序列得出抡锈。
??如果FuncOrExpressionSeq在執(zhí)行中拋出了異常錯(cuò)誤疾忍,那么ExPattern1等捕捉模式就會(huì)與它進(jìn)行匹配,找出應(yīng)該執(zhí)行哪一段表達(dá)式序列床三。ExceptionType是一個(gè)原子(throw一罩、exit和error其中之一),它告訴我們異常錯(cuò)誤是如何生成的撇簿。如果省略了ExceptionType擒抛,就會(huì)使用默認(rèn)值throw。
指令
宏定義
-define(PI,3.14).
circumference(Radius) -> Redius * 2 * ?PI.
??引用宏定義必須以問(wèn)號(hào)补疑?開(kāi)頭,在正式編譯之前歹撒,這段代碼會(huì)被展開(kāi)成
circumference(Radius) -> Redius * 2 * 3.14).
??常見(jiàn)的預(yù)定義宏:MODULE
宏莲组,它展開(kāi)后當(dāng)前正在編譯的模塊的名稱,還有FILE
和LINE
宏表示當(dāng)前處于哪個(gè)源文件的哪一行暖夭。
文件包含
-include("filename.hrl").
??預(yù)處理器會(huì)讀取被包含文件的內(nèi)容并將之插入到include指令所處的位置锹杈,這類文件一般只有聲明,沒(méi)有函數(shù)迈着,一般出現(xiàn)在模塊源文件的頭部竭望,所以也叫頭文件,按照慣例裕菠,Erlang頭文件以.hrl
為擴(kuò)展名咬清。
??-include.
指令會(huì)在當(dāng)前目錄以及列于包含路徑內(nèi)的目錄查找名為finename.hrl的文件。如果要包含其他Erlang應(yīng)用或庫(kù)的頭文件奴潘,需要使用-includelib(應(yīng)用名/include/file.erl).
指令旧烧,因?yàn)閼?yīng)用名一般帶有版本號(hào)(比如應(yīng)用名-0.0.1),使用-includelib
指令可以省略應(yīng)用名后的版本號(hào)画髓,防止因?yàn)槠渌麘?yīng)用升級(jí)造成找不到文件掘剪。
??-includelib
會(huì)相對(duì)于Erlang系統(tǒng)現(xiàn)有應(yīng)用(尤其是所有隨Erlang一并發(fā)布的標(biāo)準(zhǔn)庫(kù))的安裝路徑來(lái)查找文件。
條件編譯
-ifdef(MacroName).
xxx %如果定義了名字為MacroName的宏奈虾,就編譯這里的代碼
-ifndef(MacroName). %如果沒(méi)定義了名字為MacroName的宏夺谁,就編譯這里的代碼
-else.
-endif.
并發(fā)
??Erlang的并發(fā)是基于進(jìn)程(process)的。進(jìn)程是一些獨(dú)立的小型虛擬機(jī)肉微,可以執(zhí)行Erlang函數(shù)匾鸥。
??三個(gè)新的基本函數(shù):spawn
、send
和receive
浪册。spawn
創(chuàng)建一個(gè)并行進(jìn)程扫腺,send
向某個(gè)進(jìn)程發(fā)送消息,receive
則是接收消息村象。
??Erlang進(jìn)程意外退出時(shí)笆环,會(huì)產(chǎn)生一個(gè)退出信號(hào)攒至,所有與瀕死進(jìn)程鏈接
的進(jìn)程都會(huì)收到這個(gè)信號(hào)。默認(rèn)情況下躁劣,接收方會(huì)一并退出并將信號(hào)傳播給與它鏈接的其他進(jìn)程迫吐,直到所有直接或間接鏈接在一起的進(jìn)程系統(tǒng)退出為止。
??可以改寫(xiě)退出信號(hào)默認(rèn)的傳播行為账忘,通過(guò)設(shè)置trap_exit進(jìn)程標(biāo)記志膀,可以令進(jìn)程不再服從外來(lái)的退出信號(hào),而是將其捕捉鳖擒,這種情況下溉浙,進(jìn)程收到信號(hào)后,會(huì)先將其轉(zhuǎn)為一條格式為{'EXIT',pid,Reason}的消息蒋荚,該消息描述了哪個(gè)進(jìn)程處于什么原因而發(fā)生故障戳稽。這類會(huì)捕捉信號(hào)的進(jìn)程成為系統(tǒng)進(jìn)程,可用于匯報(bào)故障,以及重啟故障的子系統(tǒng),這類進(jìn)程也稱為監(jiān)督者销凑。
OTP
??使用OTP時(shí)彤叉,需要實(shí)現(xiàn)行為模式(類似于java里面的即接口),每種行為模式都有自己需要實(shí)現(xiàn)的函數(shù)和調(diào)用規(guī)范,比如gen_server
行為模式,實(shí)現(xiàn)模塊里面需要實(shí)現(xiàn)init/1、handle_call/3乓序、handle_cast/2、handle_info/2舟奠、terminate/2竭缝、code_change/3
回調(diào)函數(shù)。
%% 最精簡(jiǎn)的gen_server行為模式實(shí)現(xiàn)模塊
-module(...).
-behaviour(gen_server).% 行為模式實(shí)現(xiàn)的名稱
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(state,{}).
init([]) ->
{ok,#state{}}
handle_call(_Request,_Form,State) ->
Reply=ok,
{reply,Reply,State}.
handle_cast(_Msg,State) ->
{noreply,State}.
handle_info(_Info,State) ->
{noreply,State}.
terminate(_Reason,State) ->
ok.
code_change(_OldVsn,State,_Extra) ->
{ok,State}.
??實(shí)現(xiàn)了行為模式后沼瘫,還需要一個(gè)容器(功能類似于J2EE里面的容器抬纸,比如Tomcat)。容器是一個(gè)進(jìn)程耿戚,它執(zhí)行的是某個(gè)庫(kù)模塊中的代碼湿故,并且會(huì)調(diào)用與行為模式實(shí)現(xiàn)相對(duì)應(yīng)的回調(diào)模塊來(lái)處理應(yīng)用相關(guān)的邏輯,該庫(kù)模塊的名稱與對(duì)應(yīng)的行為模式的名稱一致膜蛔。
??庫(kù)模塊包含了行為模式中的通用代碼坛猪,其中包括新容器的啟動(dòng)函數(shù),比如對(duì)于gen_server
行為模式而言皂股,這部分代碼就位于Erlang/OTP庫(kù)中stdlib部分的gen_server模塊中墅茉。當(dāng)你調(diào)用gen_server:start(... , foo , ...)
時(shí),就會(huì)創(chuàng)建一個(gè)新的以foo為回調(diào)模塊的gen_server容器。我們將新容器進(jìn)程的啟動(dòng)稱作行為模式的實(shí)例化就斤。
行為模式實(shí)現(xiàn)模塊的典型布局
首部
??以%%%
開(kāi)頭表示是文件注釋悍募,@開(kāi)頭是EDoc標(biāo)注,EDoc可以直接通過(guò)源碼標(biāo)注生成文檔(與JavaDoc類似)洋机,是隨標(biāo)準(zhǔn)Erlang/OTP發(fā)行版一同發(fā)布的文檔生成工具坠宴。
%%%-------------------------------------------------------------------
%%% @author Martin & Eric <erlware-dev@googlegroups.com>
%%% [http://www.erlware.org]
%%% @copyright 2008-2010 Erlware
%%% @doc RPC over TCP server. This module defines a server process that
%%% listens for incoming TCP connections and allows the user to
%%% execute RPC commands via that TCP stream.
%%% @end
%%%-------------------------------------------------------------------
??
-module(...).
指令,與文件名對(duì)應(yīng)??
-behaviour(...)
指令绷旗,它告知編譯器這個(gè)模塊是哪個(gè)行為模式的一個(gè)實(shí)現(xiàn)喜鼓,之后必須實(shí)現(xiàn)該行為模式的所有函數(shù),否則編譯時(shí)會(huì)報(bào)錯(cuò)衔肢。??
export()
指令庄岖,通常要寫(xiě)兩個(gè),一個(gè)是自己的API角骤,一個(gè)是行為模式接口要求導(dǎo)出的函數(shù)顿锰。??接著就是一些聲明和預(yù)處理定義。
API
??API一般只是對(duì)庫(kù)模塊函數(shù)進(jìn)行一個(gè)封裝启搂。使用API可以隱藏底層使用的行為模式,使用者不需要調(diào)用庫(kù)模塊函數(shù)來(lái)啟動(dòng)容器刘陶,只需要調(diào)用API即可胳赌。
%% 調(diào)用start_link(Port)時(shí),會(huì)啟動(dòng)一個(gè)容器匙隔,進(jìn)而再調(diào)用init方法
start_link(Port) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []).
init([Port]) ->
{ok, LSock} = gen_tcp:listen(Port, [{active, true}]),
{ok, #state{port = Port, lsock = LSock}, 0}.
行為模式接口
??行為模式所需的回調(diào)函數(shù)疑苫。
內(nèi)部函數(shù)
??API和行為模式接口所需的輔助函數(shù)。