Erlang
編程範型 | 多重典範:函數式、並行 |
---|---|
設計者 | 喬·阿姆斯特朗、Robert Virding、Mike Williams |
實作者 | 愛立信 |
面市時間 | 1986年 |
目前版本 |
|
型態系統 | 動態、強 |
許可證 | Apache許可證2.0 (從OTP 18.0開始) Erlang公共許可協定1.1 (早期版本) |
副檔名 | .erl .hrl |
網站 | www |
主要實作產品 | |
Erlang | |
啟發語言 | |
Prolog, Smalltalk, PLEX,[2] LISP | |
影響語言 | |
Akka, Clojure, Dart, Elixir, F♯, Opa, Oz, Reia, Rust, Scala | |
|
Erlang(/ˈɜːrlæŋ/)是一種通用的平行導向函數式程式語言。Erlang也可以指Erlang/OTP的通稱,開源電信平台(OTP)是Erlang的常用執行環境及一系列標準元件。
Erlang 執行環境為專有以下要求的系統設計:
Erlang是運作於虛擬機的直譯式語言,但是現在也包含有烏普薩拉大學高效能Erlang計劃(HiPE)[3]開發的原生程式碼編譯器,自R11B-4版本開始,Erlang也支援腳本直譯器。在編程範型上,Erlang屬於多重典範程式語言,涵蓋函數式、平行式及分散式。循序執行的Erlang是一個及早求值, 單次賦值和動態資料形態的函數式程式語言。
它由喬·阿姆斯特朗(Joe Armstrong)在瑞典電信裝置製造商愛立信所轄的電腦科學研究室開發,目的是創造一種可以應付大規模並發活動的程式語言和執行環境。Erlang於1987年釋出正式版本,最早是愛立信擁有的私有軟體,經過十年的發展,於1998年發表開放原始碼版本。
開發及演變歷史
Erlang得名於丹麥數學家及統計學家Agner Krarup Erlang,同時Erlang還可以表示Ericsson Language。Erlang語言由瑞典愛立信電信公司的喬·阿姆斯特朗開始設計,開始於公元一九八零年代。最初是以Prolog程式語言為基礎,幾度改版之後,改成以Joe's Abstract Machine為基礎的獨立語言執行環境。雖然語言風格仍與Prolog相近,不過因Erlang語言設計的走向,Erlang成為具備函式語言特色的程式語言[4]。
發行版本
1998年起,Erlang發布開放原始碼版本,稱為開源電信平台。開源電信平台採用修改過的Mozilla公共許可證協定發放,同時愛立信仍然提供商業版本的技術支援。目前,Erlang最大的商業使用者是愛立信,其他知名使用者有北電網路、亞瑪遜以及T-Mobile等[5]。
語言特色
- 平行導向程式設計 在語言中,可以藉由spawn/*函式,將特定的函式設定為獨立的行程,之後可以做跨行程通訊。
- 函數式程式設計 由於Erlang早期以Prolog開發製成,受語言特性影響,即成為函數式語言。
- 單次賦值 每個變數只能跟資料綁一次,所以,不像一般程式語言的變數可以多次指定為不同的值。單次賦值的好處是狀態單純,使程式容易閱讀。
- 及早求值或嚴格求值 Erlang基本求值策略為電腦語言中及早求值之特性。而且,可以藉由明確使用無參數的λ演算式,將特定函式設定為惰性求值策略。
- 動態資料型態與類型系統 有編譯時期的型態檢查系統支援。
- 錯誤先發 在執行時期發生的錯誤,會由錯誤位置送出訊息,發生錯誤的行程立刻停止動作。藉由行程鏈通機制,可以自動傳遞錯誤、捕捉錯誤,使其他行程能夠幫助處理錯誤。
- 程式碼熱更新 由於Erlang是函式語言,可以撰寫特定的程式結構,製作即時更換新版函式的機制。
- 手稿語言 Erlang實作提供了指令碼執行方式。
語言構成
Erlang程式結構以函式定義為主。函式是一組將輸入分別對應到輸出的規則,對應方式遵守數學函式的慣例。此外,Erlang語言由幾項構句要素所組成,包括文字(或稱原子)、數字、列表、值組、字元、字串、二進位資料、模組、與特定用途的關鍵字如fun ... end, if ... end, case ... of ... end, spawn, !, receive ... end等等。以下段落分別列示並舉例說明Erlang程式的基本構成部份,涵蓋資料格式、表達式格式與內建函式。
資料格式
類型 | 意義與構詞規則 | 例子 |
---|---|---|
原子 | 原子是基本資料單元,以一般文字構成。構詞規則有:
|
|
數字 | 數字是基本資料單元,可以是整數或實數。
|
|
列表 | 列表是與鏈結序列相同的資料結構。任一列表大致區分為頭部與尾部,頭部是列表的第一項,尾部是列表除第一項之外的其他部份。
|
|
值組 | 值組是將二個、三個或多個資料放在一起的資料結構。
|
|
字元 | Erlang將字元存為32位元的整數。
|
|
字串 | Erlang將字串視同一列整數列表。
|
|
二進位資料 | 以左邊 << 、右邊 >> 符號,包含由位元語法(頁面存檔備份,存於網際網路檔案館)表示的資料。 |
|
函式識別項 | Erlang容許用文字表示函式識別項,使程式中可以對指定函式做函式呼叫,或者當做資料傳遞。函式識別項格式為:
|
用途見以下「函數式程式設計」小節。 |
程式代號 | Erlang容許以內建函式erlang:spawn/3、erlang:spawn/4、erlang:spawn/1、erlang:spawn/2等等,將指定函式啟動為一個程式。程式啟動之後,Erlang以左邊 < 、右邊 > ,包含一個數字和點號組成的編號,表示此程式代號。 | 見以下「平行式程式設計」小節。 |
模組 | Erlang容許將一些程式整理為一個模組。模組的設定,是在原始碼檔案開頭書寫模組標記,格式為:
-module(模組名稱). -export( [ 函數名稱/參數數目 , 函數名稱/參數數目 , ... ] ). -import( 模組名稱, [ 函數名稱/參數數目 , 函數名稱/參數數目 , ... ] ). 模組名稱和函式名稱都是原子。 -module(模組名稱) 定義模組的名字,要與檔名相同。 -export( ... ) 定義模組釋出的函式,模組內的任何函式必須要釋出才能讓外部透過模組呼叫該函式。 -import( ... ) 定義本模組要從其他模組匯入哪些函式,以便本模組自己使用。另外,為了方便程式的撰寫並測試,還容許 -compile(export_all) 定義本模組的所有函式全部對外釋出。 -compile(export_all). |
(略) |
巨集 | 巨集是將一項資料以另一個文字做為代名。
-define ( 代名 , 資料 ).
? 代名
?MODULE |
|
表達式格式
類型 | 構詞規則 | 例子 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
變數 |
變數是一種提供與資料綁定、賦值的詞彙。Erlang的變數是單一賦值,一個變數只能賦值一次。
|
| ||||||||||||||||||||||||||||
樣式匹配 |
|
| ||||||||||||||||||||||||||||
函式 |
函式是由一或多項對應規則組成。每一項規則是將一部份匹配樣式的輸入對映到相對的輸出。
原子 ( 變數 , 變數 , ... ) -> 表達式 , 表達式 , ... 在 -> 左邊是函數名稱及搭配的參數列,右邊為函數本體。
規則 ; 規則 ; ... ; 規則 . 以分號分隔一或多項規則,並最後以句號結束。 同一函數的每一規則必須以相同的原子開頭,並接受相同數量的 參數列。 函式被呼叫時,會讓呼叫方依序對被呼叫方的每一條函式規則做樣式匹配,比對函式名稱、參數數目、參數樣式等等。首先完成匹配的函式規則會被執行,並且後面的函式規則會被忽略。 |
見以下「函數式程式設計」小節 | ||||||||||||||||||||||||||||
函式呼叫 | 格式為
原子 ( 資料 , 資料 , ... ) 表示函數名稱及搭配的參數列。呼叫符合函數名稱及 相同參數數目的函數。 函式呼叫時,所給予的參數可能是已賦值的變數。並且,如果參數是變數,必須是已賦值的變數。 |
見以下「函數式程式設計」小節 | ||||||||||||||||||||||||||||
真值比較 |
真值比較的結果,如果成功則傳回true原子,失敗則傳回false原子。 請記得,Erlang是以true和false表示布林資料類型。 |
(略) | ||||||||||||||||||||||||||||
運算子 | Erlang提供常用的運算子方便基本運算。運算子是用在中序的表達式裏,包含 + - * / div(商) rem(餘) 等。位元算算有 bnot, band, bor, bxor, bsl(算術左移), bsr(算術右移) 等。用於列表有 ++(列表銜接) --(列表剔除) 等。各種運算式皆可用 ( ) 調整運算優先順序。 | (略) | ||||||||||||||||||||||||||||
防衛式(頁面存檔備份,存於網際網路檔案館) |
防衛式是接在when關鍵字之後的一組表達式,藉由防衛式的真偽值做程式控制處理。 防衛式的原則如下方所述:
|
| ||||||||||||||||||||||||||||
受防衛式限制的函式 |
函式對應規則格式為: 原子 ( 變數 , 變數 , ... ) -> 表達式 , 表達式 , ... 若一條函式規則加上防衛式,此規則的處理範圍會多一些限制。受防衛式限制的函式對應規則格式為: 原子 ( 變數 , 變數 , ... ) when 防衛式 -> 表達式 , 表達式 , ... |
| ||||||||||||||||||||||||||||
行後註解 | 任何 % 符號開頭,往後到行尾的文字皆為註解文字。 | 'H.W.'. % Hello, World! | ||||||||||||||||||||||||||||
λ演算式 |
λ演算式是匿名函式,在Erlang以 fun ... end 關鍵字敘述。格式為: fun ( 變數 , 變數 , ... ) -> 表達式 , 表達式 , ... end 使用無參數的λ演算式,可以做出惰性求值的效果。 |
| ||||||||||||||||||||||||||||
因果式 |
使用 if ... end 關鍵字敘述條件判斷原則。格式為: if 防衛式 -> 表達式, 表達式, ... ; 防衛式 -> 表達式, 表達式, ... ; ...... 防衛式 -> 表達式, 表達式, ... end |
| ||||||||||||||||||||||||||||
案例式 |
使用 case ... of ... end 關鍵字,根據一個變數的案例,帶往相對的處理程式。格式為: case 表達式 of 樣式 -> 表達式, 表達式, ... ; 樣式 -> 表達式, 表達式, ... ; ...... 樣式 -> 表達式, 表達式, ... end
|
| ||||||||||||||||||||||||||||
試誤 |
使用 try ... catch ... end 關鍵字敘述試誤的情況與結果。格式為: try 表達式 of 樣式 -> 表達式, 表達式, ... ; 樣式 -> 表達式, 表達式, ... ; ...... 樣式 -> 表達式, 表達式, ... catch 樣式(例外) -> 表達式, 表達式, ... ; 樣式(例外) -> 表達式, 表達式, ... ; ...... 樣式(例外) -> 表達式, 表達式, ... after 表達式, 表達式, ... end
|
(略) | ||||||||||||||||||||||||||||
接收訊息 |
每個Erlang程式執行時,都可以從自己程式的電子信箱中取得由其他程式送到的訊息。可以使用 receive ... end 關鍵字接收訊息,格式為: receive 樣式 -> 表達式, 表達式, ... ; 樣式 -> 表達式, 表達式, ... ; ...... 樣式 -> 表達式, 表達式, ... end
|
| ||||||||||||||||||||||||||||
傳送訊息 |
Erlang容許向程式傳送訊息。使用 ! 關鍵字,格式為: 程序代號 ! 訊息
|
| ||||||||||||||||||||||||||||
列表解析(頁面存檔備份,存於網際網路檔案館) | 列表解析,是提供快速建立列表的語法。語法等同於集合建構式(頁面存檔備份,存於網際網路檔案館)。格式為:
|
|
內建函式
開源電信平台包括一個Erlang直譯器、一個Erlang編譯器、程式節點通訊協定、CORBA、一個分散式資料庫Mnesia(頁面存檔備份,存於網際網路檔案館)、以及許多程式庫[6]。 內建函式涵蓋了各種方面的功能,涵蓋了系統命令、資料存取、格式轉換、網路通訊、圖形介面、 ... 等。以下列表介紹幾項常用的Erlang內建函式。(參閱檔案(頁面存檔備份,存於網際網路檔案館)或索引 (頁面存檔備份,存於網際網路檔案館))
模組:函式名稱 / 參數數目 | 用途 |
---|---|
c:cd / 1 |
切換到指定目錄位置。 > c:cd("D:\\code"). D:/code/ ok 當指定目錄不正確時,則保持在原目錄位置。 |
c:c / 1 |
編譯指定的程式碼,之後載入新編譯好的程式。 > c:c(test). % test.erl 必須存在於目錄位置 {ok, test} > c:c(test1). ./test1.erl:none: ... error |
io:format / 2 |
按照指定的格式文字將資料印在標準輸出埠。 > io:format("~.8B, ~c, ~s, ~.2f~n", [32, $a, "hello", 3.1416]). 40, a, hello, 3.14 ok |
lists:sublist / 3 |
由列表中擷取子列表。Erlang字串是整數列表,於是本函式視同擷取子字串。 > lists:sublist("Hello, World!", 2, 2). "el" |
Hello World 程式
這是輸出 Hello World 的一種方式:[7]
-module(hello).
-export([hello_world/0]).
hello_world() -> io:fwrite("hello, world\n").
若要編譯這個程式,將它存為一個名為 hello.erl 的文字檔,然後從 Erlang終端 進行編譯。不要忘了在每個命令的最後加上一個句號(.)。例如:
Erlang (BEAM) emulator version 4.9.1 [source] Eshell V4.9.1 (abort with ^G) 1> c(hello). {ok,hello}
(在 Unix系統 上,你可以通過在命令列裡輸入 "erl" 來進入 Erlang終端。在 Windows系統 上,你需要打開一個 命令提示符 視窗,然後輸入 "werl"來進入 Erlang終端,或者在程式功能表中找到 Erlang 的圖示。)從 Erlang終端 上運行這個程式:
2> hello:hello_world(). hello, world ok
函數式程式設計
Erlang支援函數式程式設計的一般特色,特色包括單次賦值、遞迴定義、λ演算與高階函式等等。Erlang函式大致寫法如下,以整數階乘模組為例:
-module(fact). -export([fac/1]). fac(N) when N > 1 -> N * fac(N-1); fac(1) -> 1.
以下是快速排序演算法的Erlang實作:
%% quicksort:qsort(List) %% Sort a list of items -module(quicksort). -export([qsort/1]). qsort([]) -> []; qsort([Pivot|Rest]) -> qsort([ X || X <- Rest, X =< Pivot]) ++ [Pivot] ++ qsort([ Y || Y <- Rest, Y > Pivot]).
以下是費氏數列求解函式:
-module(example). -export([fibo/1]). fibo(N) when N > 1 -> fibo(N-1) + fibo(N-2); fibo(1) -> 1; fibo(0) -> 0.
> c(example). {ok,example} > lists:map(fun(X)->example:fibo(X) end, lists:seq(1,10)). [1,1,2,3,5,8,13,21,34,55]
函數式程式設計難免以遞迴計算,而消耗了大量遞迴堆疊空間。為了克服這個問題,一般使用累積參數與尾端遞迴等技巧節省遞迴數目:如以下例子。
-module(test). -export([fibo_accu/1]). fibo_accu(N) -> fibo(N, 0, 1). fibo(N, C1, C2) when N > 2 -> fibo(N-1, C2, C1+C2); fibo(0, _, _) -> 0; fibo(1, _, _) -> 1; fibo(_, C1, C2) -> C1+C2.
> c(example). {ok,test} > lists:map(fun(X)->test:fibo_accu(X) end, lists:seq(1,10)). [1,1,2,3,5,8,13,21,34,55]
函數式程式設計容許使用高階函式求解。以下例子說明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/1, fun test:parse/1))(3.1416). Real number 3.141600 is met. ok
平行式程式設計
Erlang最主要的特色是平行導向程式設計,強調多程式平行運作,並且以訊息對彼此溝通[8]。Erlang提供了spawn函式和 ! 、 receive ... end 等關鍵字,可以描述在Erlang/開源電信平台中的如何啟動一些程式、並且如何讓程式傳遞訊息。此外,平行導向程式設計的精神還強調程式的容錯處理,藉由程式發生錯誤時的訊息傳遞,使其他程式可以得知錯誤的發生,使方便於後續處理。以下分別介紹平行導向程式設計的一般程式撰寫方式,以及錯誤處理的使用方式。
平行導向程式設計
基本的平行程式示範如下:
- 以下啟動一個程式。
% create process and call the function web:start_server(Port, MaxConnections) ServerProcess = spawn(web, start_server, [Port, MaxConnections]),
- 以下是在任何程式中,對先前起動的程式送一則訊息 {pause, 10} 。
% send the {pause, 10} message (a tuple with an atom "pause" and a number "10") % to ServerProcess (asynchronously) ServerProcess ! {pause, 10},
- 以下是一段接收訊息的程式。每個程式都擁有一份電子信箱,可佇留收到的訊息; 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(1, 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]). [<0.233.0>,<0.234.0>,<0.232.0>] > P ! stop. Stop process <0.233.0> stop Stop process <0.234.0> > Stop process <0.232.0> >
容錯處理
Erlang容錯處理機制,由二個步驟實現:一是將二個程式連接起來,二者之間存在一道通訊管道,可提供錯誤訊息的傳遞 ── 在此使用link/1函式;二是將程式回報錯誤的機制打開 ── 在此使用process_flag/2函式。
- 使用link(Pid)讓程式連接到另一個程式。
-module(example). -compile(export_all). hello() -> Pid = spawn(?MODULE, world, []), link(Pid), ... . 執行時,以 Pid = spawn(example, hello, []) 啟動程序,此程序將啟動另一個程序,並且與它連接。
- 但以上程式還不會有錯誤訊息的傳遞機制,因為回報錯誤的開關還沒有打開。
- 開啟程式回報錯誤機制。
以上 hello/0 函數前段使用process_flag/2函數,將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_1
- 在同一個網域中,網路節點名稱可以使用短名。
$> erl -sname node_1
啟動新的網路節點時,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、... 等模組,做網路通訊[9]。
其他程式設計典範
惰性求值
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/0, then(literal($+), fun factor/0)), then(fun factor/0, then(literal($-), fun factor/0))) end. factor() -> fun () -> alt(then(fun term/0, then(literal($*), fun term/0)), then(fun term/0, then(literal($/), fun term/0))) end. term() -> fun () -> alt(number(), xthen(literal($(), thenx(expr(), literal($))))) end.
應用
- Wings 3D,一個用Erlang編寫的三維計算機圖形軟體。
- YAWS(頁面存檔備份,存於網際網路檔案館),以Erlang編寫的高效HTTP伺服器。
- DISCO(頁面存檔備份,存於網際網路檔案館),以Erlang編寫的MapReduce架構系統。
- Apache CouchDB(頁面存檔備份,存於網際網路檔案館),以Erlang編寫的MapReduce檔案式資料庫系統。
- RabbitMQ(頁面存檔備份,存於網際網路檔案館),能搭配Erlang運作的訊息佇列系統。
- 開放電信平台
- WhatsApp:其後端伺服器應用使用了Erlang及FreeBSD[10]。支援了4.5億的活躍使用者
- ejabberd(頁面存檔備份,存於網際網路檔案館),世界上最流行的XMPP即時通訊伺服器
- EMQX(頁面存檔備份,存於網際網路檔案館),以Erlang編寫的高可用、分散式MQTT訊息伺服器。
社群
- Erlang Central(英文)
- Erlang Resources 豆瓣小站(頁面存檔備份,存於網際網路檔案館)(簡體中文)
- Erlang中文社區 erlang-china.org(簡體中文)
- Erlang中文教程 erlang-cn.com(頁面存檔備份,存於網際網路檔案館)(簡體中文)
- Erlang中文社群 cnerlang.com(簡體中文)
- Erlang中文 erlang-cn.org(簡體中文)
參考資料
- ^ Release 27.1.2. 2024年10月17日 [2024年10月18日].
- ^ 18:30. [2018-05-05]. (原始內容存檔於2017-07-15).
- ^ High Performance Erlang. [2008-04-13]. (原始內容存檔於2011-06-16).
- ^ Coders At Work. Book introduction. [2010-08-30]. (原始內容存檔於2010-03-05).見Coders At Work一書對Joe Armstrong的口述記錄。
- ^ Who uses Erlang for product development?. Frequently asked questions about Erlang. [2008-04-13]. (原始內容存檔於2008-04-19). 「The largest user of Erlang is Ericsson. Ericsson use it to write software used in telecommunications systems. Many (dozens) projects have used it, a particularly large one is the extremely scalable AXD301 ATM switch.」 FAQ中列出的其他使用者包括: Nortel、Deutsche Flugsicherung、T-Mobile等
- ^ 存档副本. [2010-09-03]. (原始內容存檔於2011-05-12).
- ^ 譯自官網 http://www.erlang.org/faq/getting_started.html (頁面存檔備份,存於網際網路檔案館)
- ^ Armstrong, Joe. Erlang. Communications of the ACM. September 2010, 53 (9): 68–75. doi:10.1145/1810891.1810910.
Erlang is conceptually similar to the occam programming language, though it recasts the ideas of CSP in a functional framework and uses asynchronous message passing.
- ^ 參考分散式Erlang (頁面存檔備份,存於網際網路檔案館), http://www.erlang.org/doc/reference_manual/distributed.html (頁面存檔備份,存於網際網路檔案館)
- ^ Erlang及FreeBSD存档副本. [2014-02-22]. (原始內容存檔於2014-02-25).
延伸閱讀
- Armstrong, Joe. Making reliable distributed systems in the presence of software errors (PDF). Ph.D. Dissertation. The Royal Institute of Technology, Stockholm, Sweden. 2003 [2016-02-13]. (原始內容存檔 (PDF)於2015-03-23).
|url-status=
和|dead-url=
只需其一 (幫助) - Armstrong, Joe. A history of Erlang. Proceedings of the third ACM SIGPLAN conference on History of programming languages – HOPL III. 2007: 6–1. ISBN 978-1-59593-766-7. doi:10.1145/1238844.1238850.
- Early history of Erlang(頁面存檔備份,存於網際網路檔案館) by Bjarne Däcker
- Mattsson, H.; Nilsson, H.; Wikstrom, C. Mnesia – A distributed robust DBMS for telecommunications applications. First International Workshop on Practical Aspects of Declarative Languages (PADL '99). 1999: 152–163.
- Armstrong, Joe; Virding, Robert; Williams, Mike; Wikstrom, Claes. Concurrent Programming in Erlang 2nd. Prentice Hall. 1996-01-16: 358 [2019-10-16]. ISBN 978-0-13-508301-7. (原始內容存檔於2012-03-06).
- Armstrong, Joe. Programming Erlang: Software for a Concurrent World 1st. Pragmatic Bookshelf. 2007-07-11: 536. ISBN 978-1-934356-00-5.
- Thompson, Simon J.; Cesarini, Francesco. Erlang Programming: A Concurrent Approach to Software Development 1st. Sebastopol, California: O'Reilly Media, Inc. 2009-06-19: 496 [2020-01-20]. ISBN 978-0-596-51818-9. (原始內容存檔於2019-10-16).
- Logan, Martin; Merritt, Eric; Carlsson, Richard. Erlang and OTP in Action 1st. Greenwich, CT: Manning Publications. 2010-05-28: 500. ISBN 978-1-933988-78-8.
- Martin, Brown. Introduction to programming in Erlang, Part 1: The basics. developerWorks. IBM. 2011-05-10 [2011-05-10]. (原始內容存檔於2019-10-16).
- Martin, Brown. Introduction to programming in Erlang, Part 2: Use advanced features and functionality. developerWorks. IBM. 2011-05-17 [2011-05-17]. (原始內容存檔於2019-10-16).
- Wiger, Ulf. Four-fold Increase in Productivity and Quality: Industrial-Strength Functional Programming in Telecom-Class Products (PDF). FEmSYS 2001 Deployment on distributed architectures. Ericsson Telecom AB. 2001-03-30 [2014-09-16]. (原始內容存檔 (PDF)於2019-08-19).