Erlang
Erlang(/ ˈɜːrlæŋ /)是一種通用的平行導向函數式程式語言。Erlang 嘛會當指 Erlang / OTP 的通稱,開源電信平台(OTP)是 Erlang 的常用執行環境佮一系列標準元件。
Erlang 執行環境為專有以下要求的系統設計:
- 散式運算
- 高故障容許度
- 軟性即時運算
- 懸可用性、直直做出來的應用
- 熱插拔,會當修改程式而免停機
Erlang 是運作佇虛擬機的直譯式語言,但是這馬嘛包含有烏普薩拉大學高效能 Erlang 計畫(HiPE)開發的原生程式碼編譯器,自 R 十一 B 枋仔四版本開始,Erlang 嘛支援跤本直譯器。佇咧編程範型上,Erlang 是屬於多重典範程式語言,涵蓋函數式、平行式佮分散式。循序執行的 Erlang 是一个古早求值,單次才閣動態資料形態的函數式程式語言。
伊由喬 ・ 阿姆斯特朗(Joe Armstrong)佇瑞典電信裝置製造商愛立信所轄的電腦科學研究室開發,目的是創造一種會當應付大規模閣發活動的程式語言佮執行環境。Erlang 佇一九八七年釋出正式的版本,上早是愛立信擁有的私有軟體,經過十冬的發展,佇一九九八年發表開放原始碼版本。
開發佮演變歷史
Erlang 著名佇丹麥數學家佮統計學家 Agner Krarup _ Erlang _,同時 Erlang 閣會當表示 _ Er _ icsson _ Lang _ uage。Erlang 語言由瑞典愛立信電信公司的喬 ・ 阿姆斯特朗開始設計,開始公元一九八空年代。頭仔是以 Prolog 程式語言做基礎,幾度改版了後,改做以 Joe's Abstract Machine 為基礎的獨立語言執行環境。雖然語言的風格猶原和 Prolog 相倚,猶毋過咧乎 Erlang 語言設計的行向,Erlang 成做具備函式語言特色的程式語言。
發行版本
一九九八年起,Erlang 發佈開放原始碼版本,號做開源電信平台。開源電信平台採用修改過的 Mozilla 公共許可證協定來發放,同時愛立信猶閣提供商業版本的技術支援。目前,Erlang 上大的商業使用者是愛立信,其他有名的使用者有北電網路、亞瑪綴袂著 T-Mobile 等。
語言特色
- 平行導向程式設計佇語言內底,會當透過 spawn / \ * 函式,將特定的函式設定做獨立的行程,了後會使做跨行程通訊。
- 函數式程式設計因為 Erlang 早期以 Prolog 開發製作,受著語言特性影響,就成做函數式的語言。
- 單次才值逐个變數干焦會當佮資料縛一改,所以乎,無親像講一般程式語言的變數會當多次指定為無仝的值。單次才值的好處是狀態單純,使程式會當閱讀。
- 佮早求值抑是嚴格求值Erlang 基本求值策略為電腦語言內底佮早求值之特性。而且,會當藉著明確來使用無參數的 λ 演算式,將特定函式設定做貧惰性求值策略。
- 動態資料型態佮類型系統有編譯時期的型態檢查系統支援。
- 錯誤先發佇執行時期發生的錯誤,會由錯誤位置送出訊息,發生錯誤的行程隨停止動作。藉由行程鏈通機制,會當自動傳遞錯誤、掠毋著,使其他行程會使幫助處理錯誤。
- 程式碼熱更新因為 Erlang 是函式的語言,會當編寫特定的程式結構,製作即時換新版函式的機制。
- 手稿語言Erlang 實作提供了指令碼執行方式。
語言構成
Erlang 程式結構以函式定義做主。函式是一組將輸入分別對應到輸出的規則,對應方式遵守數學函式的慣例。此外,Erlang 語言由幾項構句要素所組成,包括文字 ( 抑是講原子 )、數字、列表、值組、字元、字捾、二進位資料、模組、佮特定用途的關鍵字如 fun . . . end , if . . . end , case . . . of . . . end , spawn , ! , receive . . . end 等咧。以下段落分別列示並舉例說明 Erlang 程式的基本構成部份,涵蓋資料的格式、表達式格式佮內建函式。
資料的格式
表達式格式
內建函式
開源電信平台包括一个 Erlang 直譯器、一个 Erlang 編譯器、程式節點通訊協定、CORBA、一个分散式的資料庫 Mnesia、猶閣有足濟程式庫。內建函式涵蓋各種方面的功能咧,涵蓋系統命令、資料的存取、格式轉換、網路通訊、圖形介面、. . . 等。以下列表介紹幾項常用的 Erlang 內建函式。( 參閱檔案抑是索引 )
Hello World 程式
這是輸出 Hello World 的一種方式:
若欲編譯這个程式乎,為一个存在為一个 hello . erl 的文字檔,然後對 Erlang 終端進行編譯。毋通袂記得佇每一个命令的最後加上一个句號(.)。 比如講:
` ` ` Erlang ( BEAM ) emulator version 四配九 . 一 [source] Eshell V 四配九 . 一 ( abort with ^ G ) 一 > c ( hello ) . { ok , hello } ` ` `
( 佇咧 Unix 系統上,你會當通過佇命令列內底輸入 " erl " 來進入 Erlang 終其尾。佇咧 Windows 系統上,你需要拍開一个命令提示符視窗,然後輸入 " werl " 來進入 Erlang 終其尾,抑是佇程式功能表內底揣著 Erlang 的圖示。)對 Erlang 終端上運行這个程式:
` ` ` 二 > hello : hello _ world ( ) . hello , world ok ` ` `
函數式程式設計
Erlang 支援函數式程式設計的一般特色,特色包括孤一改孤一改、遞迴定義、λ 演算來佮高階函式等等。Erlang 函式大致寫法這馬,以整數階乘模組做例:
` ` ` -module( fact ) . -export( [fac / 一] ) .
fac ( N )whenN > 一-> N * fac ( N 影一 ) ; fac ( 一 )-> 一 . ` ` `
以下是快速排序演算法的 Erlang 實作:
` ` ` _ % % quicksort : qsort ( List ) _ _ % % Sort a list of items _ -module( quicksort ) . -export( [qsort / 一] ) .
qsort ( [] )-> [] ; qsort ( [Pivot | Rest] )-> qsort ( [X | | X <-Rest , X=< Pivot] ) + + [Pivot] + + qsort ( [Y | | Y <-Rest , Y > Pivot] ) . ` ` `
以下是費氏數列求解函式:
` ` ` -module( example ) . -export( [fibo / 一] ) .
fibo ( N )whenN > 一-> fibo ( N 影一 ) + fibo ( N 鋪二 ) ; fibo ( 一 )-> 一 ; fibo ( 零 )-> 零 . ` ` `
` ` ` > c ( example ) . { ok , example } > lists : map ( fun ( X )->example : fibo( X ) end , lists : seq ( 一 , 十 ) ) . [一 , 一 , 二 , 三 , 五 , 八 , 十三 , 二十一 , 三十四 , 五十五] ` ` `
函數式程式設計難免用遞迴計算,煞閣消磨大量遞迴疊空間。為著克服這个問題,一般使用累積參數佮尾溜遞迴等技巧節省遞迴數目:以下比如講以下。
` ` ` -module( test ) . -export( [fibo _ accu / 一] ) .
fibo _ accu ( N )-> fibo ( N , 零 , 一 ) . fibo ( N , C 一 , C 二 )whenN > 二-> fibo ( N 影一 , C 二 , C 一 + C 二 ) ; fibo ( 零 , _ , _ )-> 零 ; fibo ( 一 , _ , _ )-> 一 ; fibo ( _ , C 一 , C 二 )-> C 一 + C 二 . ` ` `
` ` ` > c ( example ) . { ok , test } > lists : map ( fun ( X )->test : fibo \ _ accu( X ) end , lists : seq ( 一 , 十 ) ) . [一 , 一 , 二 , 三 , 五 , 八 , 十三 , 二十一 , 三十四 , 五十五] ` ` `
函數式程式設計容許使用高階函式求解。比如講比如講 Erlang 實做複合函式。( f o g,唸作 f _ after _ g。)
` ` ` 'After'( F , G )-> fun ( X )-> erlang : apply ( F , [erlang : apply ( G , [ X] ) ] ) end . ` ` `
- * 請注意after是 Erlang 關鍵字。所以,以上函式號名做 ′ _ After _ ′ 避開關鍵字。
` ` ` > (example :'After'( fun test : show / 一 , fun test : parse / 一 ) ) ( 三-c一四一六 ) . Real number 三-c一四一六空空 is met . ok ` ` `
平行式程式設計
Erlang 上主要的特色是平行導向程式設計,強調濟程式平行運作,而且以訊息對彼此溝通。Erlang 提供矣spawn函式佮!、receive. . .end等等關鍵字,會當描述講是佇 Erlang / 開源電信平台中的按怎啟動一寡程式、並且欲按怎予程式傳遞訊息。此外,平行導向程式設計的精神閣強調程式的容錯處理,藉著程式發生錯誤時的訊息傳達,予其他程式會當知影毋著的發生,予方便於後續處理。以下分別介紹平行導向程式設計的一般程式編寫方式,閣有錯誤處理的使用方式。
平行導向程式設計
基本的平行程式示範如下:
- 以下啟動一个程式。
` ` ` _ % create process and call the function web : start \ _ server ( Port , MaxConnections ) _ ServerProcess=spawn( web , start _ server , [Port , MaxConnections] ) , ` ` `
- 以下是佇任何程式當中,對早前起動的程式送一个訊息 { _ pause _ , _ 十 _ }。
` ` ` _ % send the { pause , 十 } message ( a tuple with an atom " pause " and a number " 十 " ) _ _ % to ServerProcess ( asynchronously ) _ ServerProcess ! { pause , 十 } ,
` ` `
- 以下是一段接收訊息的程式。逐个程式攏有一份電子信箱,有可以留收著的訊息;receive . . . end 程式片斷是對程式的電子信箱當中取出上早佇留的訊息。
` ` ` _ % receive messages sent to this process _ receive a _ message-> do _ something ; { data , DataContent }-> handle ( DataContent ) ; { hello , Text }-> io : format ( " Got hello message : ~ s " , [Text] ) ; { goodbye , Text }-> io : format ( " Got goodbye message : ~ s " , [Text] ) end.
收著_ a \ _ message _ 結果就是 _ do \ _ something _;收著 { _ data _ , _ DataContent _ } 結果會呼叫 handle ( DataContent ); 收著 { _ hello _ , _ Text _ } 結果教是印出 " Got hello message : . . . ",收著 { _ goodbye _ , _ Text _ } 結果印出 " Got goodbye message : . . . "。 ` ` `
以下程式,示範產生一組環狀傳遞訊息的程式。
` ` ` ring _ proc ( Funs )-> Ns=lists : seq ( 一 , length ( Funs ) ) , [P | Pids]=[spawn( _ ? MODULE _ , lists : nth ( Nth , Funs ) , [] ) | | Nth <-Ns] , [Pid ! ToPid | | { Pid , ToPid } <-lists : zip ( [ P | Pids] , Pids + + [P] ) ] .
func ( )-> receive ToPid-> func _ msg _ ( ToPid ) end.
func _ msg _ ( ToPid )-> receive stop-> io : format ( " Stop process ~ w ~ n " , [self ( )] ) , ToPid ! stop ; Message-> io : format ( " ~ w : transmit message to ~ w ~ n " , [self ( ) , ToPid] ) , ToPid ! Message , func _ msg _ ( ToPid ) end.
接收 _ stop _ 訊息,就對後一个程序送 _ stop _ 訊息;接收著其他任何的訊息,就對後一个程序送仝款的訊息。 ` ` `
若是傳送任何其他的訊息,就會予所有的程式不斷對後一个程式傳遞訊息。以下是咧測試傳送 _ stop _ 訊息的執行結果。
` ` ` > [P| _ ]=example : ring \ _ proc( [func , func , func] ) . [< 空九二三三 . 零 > , < 空九二三四 . 零 > , < 空九二三二 . 零 >] >P ! stop . Stop process < 空九二三三 . 零 > stop Stop process < 空九二三四 . 零 > > Stop process < 空九二三二 . 零 > > ` ` `
容錯處理
Erlang 容錯處理機制,由兩步驟現:一是共兩个程式連接起來,二者之間存在一道通訊的管道,會當提供錯誤訊息的傳達 ─ ─ 在此使用link/一函式;二是將程式回報錯誤的機制拍開 ─ ─ 在此使用process \ _ flag/二函式。
- 使用 link ( _ Pid _ ) 予程式連接到另外一个程式。
` ` ` -module( example ) . -compile( export _ all ) . hello ( )-> _ Pid _=spawn ( ? MODULE , world , [ ] ) , link ( _ Pid _ ) , . . . .
執行的時,以 Pid=spawn( _ example _ , _ hello _ , [ ] ) 起動的程序,這个程序共啟動另外一个程序,並且佮伊連接。 ` ` `
- 毋過以上程式閣袂有錯誤訊息的傳達機制,因為回報錯誤的開關猶未拍開。
- 開啟程式回報錯誤機制。
` ` ` 以上 hello / 空函數頭前段使用process \ _ flag/二函數,將 _ trap \ _ exit _ 標籤拍開,就會當趕緊開啟程序回報錯誤機制。 ` ` `
` ` ` hello ( )-> process \ _ flag( _ trap \ _ exit _ , _ true _ ) , Pid=spawn ( ? MODULE , world , [ ] ) , link ( Pid ) , . . . . ` ` `
所以,當程式結束的時陣,會送出 {'EXIT', _ From _ , _ Reason _ } 資料。程式正常結束的時陣,_ Reason _ 為 _ normal _。
另外咧,spawn函式另外有程式連接版本,spawn \ _ link函式,同時啟動閣連接著新的程式。
分散式程式設計
Erlang 提供分散式的機制,會當佇另外一台電腦啟動一寡 Erlang 程式,閣由本機電腦著其他電腦的 Erlang 程式傳遞訊息。
- 當啟動 Erlang 環境的時,加上一个網路節點名講,就進入分散式 Erlang 模式。節點會當使用埠號佮其他節點通訊。
` ` ` $ >erl-name node _ 一 ` ` `
- 佇仝一个網仔內底,網路節點名會當使用短名。
` ` ` $ >erl-sname node _ 一 ` ` `
啟動新的網路節點鐘,Erlang 使用epmd( Erlang 埠號對應管理系統 ) 指派埠號,提供節點來使用。
當知影講一个網路節點名的時陣,會當佇這个節點產生新的程式。
- 咧指定節點 _ RemoteNode _ 啟動一个程式,spawn啟動參數依序做節點名、模組名稱、函式名稱、函式的參數列。
` ` ` _ % create a remote process and call the function web : start \ _ server ( Port , MaxConnections ) _ _ % on machine RemoteNode _ RemoteProcess=spawn( _ RemoteNode _ , web , start _ server , [Port , MaxConnections] ) ,
佇遠端節點產生新程序了後,會當使用平行式程式設計的技巧,佮遠端的程序通訊。 ` ` `
Erlang / 開源電信平台提供的程式庫,佇分散式程式設計會當使用 _ net \ _ adm _、_ net \ _ kernel _、_ slave _、. . . 等模組,做網路通訊。
其他程式設計典範
慢性求值
Erlang 程式員會當使用伊慢性求值。猶毋過,著愛使用 λ 演算式,才會當做伊的貧惰性求值。
` ` ` 以下是慢性求值的一例:準講有一个剖析的器程式通好,因為較早求值特徵,本程式會求解。 expr ( )-> alt ( then ( factor ( ) , then ( literal ( $ + ) , factor ( ) ) ) , then ( factor ( ) , then ( literal ( $-) , factor ( ) ) ) ) . factor ( )-> alt ( then ( term ( ) , then ( literal ( $ * ) , term ( ) ) ) , then ( term ( ) , then ( literal ( $ / ) , term ( ) ) ) ) . term ( )-> alt ( number ( ) , xthen ( literal ( $ ( ) , thenx ( expr ( ) , literal ( $ ) ) ) ) ) . 此使用 λ 演算式佮適當使用函數名稱表示,就會當進行求值。示比如講下底。 expr ( )-> fun ( )-> alt ( then ( fun factor / 零 , then ( literal ( $ + ) , fun factor / 零 ) ) , then ( fun factor / 零 , then ( literal ( $-) , fun factor / 零 ) ) ) end . factor ( )-> fun ( )-> alt ( then ( fun term / 零 , then ( literal ( $ * ) , fun term / 零 ) ) , then ( fun term / 零 , then ( literal ( $ / ) , fun term / 零 ) ) ) end . term ( )-> fun ( )-> alt ( number ( ) , xthen ( literal ( $ ( ) , thenx ( expr ( ) , literal ( $ ) ) ) ) ) end . ` ` `
應用
- Wings 三 D,一用 Erlang 編寫的三維計算機圖形軟體。
- YAWS,以 Erlang 編寫的高效 HTTP 侍服器。
- DISCO,以 Erlang 編寫的 MapReduce 架構系統。
- Apache CouchDB,以 Erlang 編寫的 MapReduce 檔案式的資料庫系統。
- RabbitMQ,會當配搭 Erlang 運作的訊息佇咧列系統。
- 開放電信平台
- WhatsApp:其後捀服器應用使用矣Erlang佮 FreeBSD。支援矣四配五億的活跳使用者
- ejabberd , 世界上時行的 XMPP 即時通訊侍服器
- EMQX,以 Erlang 編寫的懸可用、散式 MQTT 訊息侍服器。
社群
- Erlang Central(英文)
- Erlang Resources 豆瓣小站(簡體中文)
- Erlang 中文社區 erlang-china . org(簡體中文)
- Erlang 中文教程 erlang-cn . com(簡體中文)
- Erlang 中文社群 cnerlang . com(簡體中文)
- Erlang 中文 erlang-cn . org(簡體中文)
參考資料
延伸閱讀
外部連結
- Erlang 開放原始碼版本(英文)
- Erlang 愛立信授權版本(英文)
- 因應軟體錯誤建構會當靠的分散式系統(英文)
- 開放式 kha-tá-lok-guh 計畫中和 Erlang 相關的內容
- Erlang 教學