Erlang

Erlang（ˈ）是一種通用的平行導向函數式程式語言。Erlang也可以指Erlang/OTP的通稱，開源電信平台（OTP）是Erlang的常用執行環境及一系列標準元件。

Erlang 執行環境為專有以下要求的系統設計：

- 分散式運算
- 高故障容許度
- 軟性即時運算
- 高可用性、不停運作的應用
- 熱插拔，可以修改程式而不必停機

Erlang是運作於虛擬機的直譯式語言，但是現在也包含有烏普薩拉大學高性能Erlang計劃（HiPE）開發的原生程式碼編譯器，自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成為具備函數語言特色的程式語言。

### 發行版本

1998年起，Erlang發布開放源碼版本，稱為開源電信平台。開源電信平台採用修改過的Mozilla公共許可證協議發放，同時愛立信仍然提供商業版本的技術支持。目前，Erlang最大的商業使用者是愛立信，其他知名使用者有北電網路、亞瑪遜以及T-Mobile等。

### 語言特色

- 平行導向程式設計 在語言中，可以藉由spawn/*函數，將特定的函數設定為獨立的行程，之後可以做跨行程通訊。
- 函數式程式設計 由於Erlang早期以Prolog開發製成，受語言特性影響，即成為函數式語言。
- 單次賦值 每個變數只能跟資料綁一次，所以，不像一般程式語言的變數可以多次指定為不同的值。單次賦值的好處是狀態單純，使程式容易閱讀。
- 及早求值或嚴格求值 Erlang基本求值策略為電腦語言中及早求值之特性。而且，可以藉由明確使用無參數的λ演算式，將特定函數設定為惰性求值策略。
- 動態資料型態與類型系統 有編譯時期的型態檢查系統支援。
- 錯誤先發 在執行時期發生的錯誤，會由錯誤位置送出訊息，發生錯誤的行程立刻停止動作。藉由行程鏈通機制，可以自動傳遞錯誤、捕捉錯誤，使其他行程能夠幫助處理錯誤。
- 程式碼熱更新 由於Erlang是函數語言，可以撰寫特定的程式結構，製作即時更換新版函數的機制。
- 腳本語言 Erlang實作提供了腳本執行方式。

## 語言構成

Erlang程式結構以函數定義為主。函數是一組將輸入分別對應到輸出的規則，對應方式遵守數學函數的慣例。此外，Erlang語言由幾項構句要素所組成，包括文字(或稱原子)、數字、列表、值組、字元、字串、二進位資料、模組、與特定用途的關鍵字如fun ... end, if ... end, case ... of ... end, spawn, !, receive ... end等等。以下段落分別列示並舉例說明Erlang程式的基本構成部份，涵蓋資料格式、表達式格式與內建函數。

### 資料格式

類型｜意義與構詞規則｜例子

原子｜原子是基本資料單元，以一般文字構成。構詞規則有： # 以小寫英文字元開頭、不包含空白的連續文字。# 以單引號包含的任意連續文字。｜、hello、'Hello, World!'、true、a3b

數字｜數字是基本資料單元，可以是整數或實數。# 連續數字符號。# 包含一個小數點的連續數字符號，並不以小數點開頭也不以小數點結尾。# 符合前二項原則，並以 + 或 - 符號開頭。# 以`#`分割的數字，前者將表示進位。｜、302、3.1416、+1、-2、`16#10`

列表｜列表是與鏈接序列相同的資料結構。任一列表大致區分為頭部與尾部，頭部是列表的第一項，尾部是列表除第一項之外的其他部份。# 左邊以、右邊以 符號，包含一串以逗號分隔的零或多項構句要素。# 符合前項原則，當存在任一 | 符號時， | 的左邊有一串逗號分隔的構句要素， | 的右邊只有一個構句要素。｜* * 1,2,3、1,2|

值組｜值組是將二個、三個或多個資料放在一起的資料結構。、左邊以 {、右邊以 } 符號，包含一串以逗號分隔的零或多項構句要素。｜、{}、1},2}

字元｜Erlang將字元存為32位元的整數。# 任何可見的字元，以 $ 開頭、後接該字元符號，即表示字元本身。# 任何不可見的字元，可使用以 $ 開頭、後接該字元符號的轉義序列表達。｜、$3、$)、$\012、$\x0A、$\n

字串｜Erlang將字串視同一列整數列表。# 以雙引號包含任意多個文字，即為字串。# 以一列整數列表表達，使其中每個整數項目都落在合理的字元的值範圍，此列也是字串。｜、"Hello, World!"、65,66,67

二進位資料｜以左邊 > 符號，包含由 位元語法表示的資料。｜、>、>

函數識別項｜Erlang容許用文字表示函數識別項，使程式中可以對指定函數做函數呼叫，或者當做資料傳遞。函數識別項格式為：、fun 函數名稱/參數數目｜、fun a_function/3 用途見以下「函數式程式設計」小節。

程序代號｜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 ( 代名 , 資料 ).、使用巨集的語法是： ? 代名、Erlang有一些內定語法，例如模組名稱為 ?MODULE｜、-define(hello, world). : test -> ?hello.

### 表達式格式

類型｜構詞規則｜例子

變數｜變數是一種提供與資料綁定、賦值的詞彙。Erlang的變數是單一賦值，一個變數只能賦值一次。# 以大寫英文字元開頭的任意連續文字，是具名變數。# 以 _ 開頭的任意連續文字，是匿名變數，用於變數必須使用、但相對的值可以忽略的場合。｜、Number1、_、_nothing

樣式匹配｜# 樣式是指以原子、列表或值組表達的結構，結構中可能包含一些未賦值的變數。# 給二個樣式 A 和 B，樣式匹配是用 A = B 表示法，表示要讓 A 對 B 匹配。如果匹配成功， A 包含的未賦值變數都會賦值，並且傳回 B 的值。｜、A = 42、{ok, Node} = {ok, 'Wikipedia'}、T = 1,2,3

函數｜函數是由一或多項對應規則組成。每一項規則是將一部份匹配樣式的輸入映射到相對的輸出。、規則：格式為 原子 ( 變數 , 變數 , ... ) -> 表達式 , 表達式 , ... 在 -> 左邊是函數名稱及搭配的參數列，右邊為函數本體。、函數：格式為 規則 ; 規則 ; ... ; 規則 . 以分號分隔一或多項規則，並最後以句號結束。同一函數的每一規則必須以相同的原子開頭，並接受相同數量的 參數列。函數被呼叫時，會讓呼叫方依序對被呼叫方的每一條函數規則做樣式匹配，比對函數名稱、參數數目、參數樣式等等。首先完成匹配的函數規則會被執行，並且後面的函數規則會被忽略。｜見以下「函數式程式設計」小節

函數呼叫｜格式為 原子 ( 資料 , 資料 , ... ) 表示函數名稱及搭配的參數列。呼叫符合函數名稱及 相同參數數目的函數。函數呼叫時，所給予的參數可能是已賦值的變數。並且，如果參數是變數，必須是已賦值的變數。｜見以下「函數式程式設計」小節

真值比較｜、比較運算： :

`==`｜相等 /=｜不相等 ==｜大於或等於 >｜大於 =:=｜確實相等 =/=｜確實不相等、真值運算： : not｜非 and｜且 or｜或 xor｜非此即彼 orelse｜或 (捷徑求值) andalso｜且 (捷徑求值) 真值比較的結果，如果成功則傳回true原子，失敗則傳回false原子。請記得，Erlang是以true和false表示布林資料類型。｜(略)

運算子｜Erlang提供常用的運算子方便基本運算。運算子是用在中序的表達式裏，包含 + -、/ div(商) rem(餘) 等。位元算算有 bnot, band, bor, bxor, bsl(算術左移), bsr(算術右移) 等。用於列表有 ++(列表銜接) --(列表剔除) 等。各種運算式皆可用 調整運算優先順序。｜(略)

防衛式｜防衛式是接在when關鍵字之後的一組表達式，藉由防衛式的真偽值做程式控制處理。防衛式的原則如下方所述： # 代表true或false的變數或原子，是防衛式。# 任何真值運算式，包括比較算式和邏輯算式，是防衛式。# 傳回true或false的函數呼叫，是防衛式。# 以逗號分隔的多個防衛式，是防衛式。｜、false、A =< 10、erlang:is_number(N), erlang:is_atom(A)

受防衛式限制的函數｜函數對應規則格式為：原子 ( 變數 , 變數 , ... ) -> 表達式 , 表達式 , ... 若一條函數規則加上防衛式，此規則的處理範圍會多一些限制。受防衛式限制的函數對應規則格式為：原子 ( 變數 , 變數 , ... ) when 防衛式 -> 表達式 , 表達式 , ...｜、atom_pair(A, B) when is_atom(A), is_atom(B) -> {A, B}.

行後註解｜任何 % 符號開頭，往後到行尾的文字皆為註解文字。｜'H.W.'. % Hello, World!

λ演算式｜λ演算式是匿名函數，在Erlang以 fun ... end 關鍵字敘述。格式為： fun ( 變數 , 變數 , ... ) -> 表達式 , 表達式 , ... end 使用無參數的λ演算式，可以做出惰性求值的效果。｜、(fun(X)->X>0 end)(1). :% (λ x . x > 0) 1、lists:takewhile( :fun(X)-> :X>0 and X=<10 end, :1,5,11).

因果式｜使用 if ... end 關鍵字敘述條件判斷原則。格式為： if 防衛式 -> 表達式, 表達式, ... ; 防衛式 -> 表達式, 表達式, ... ; ...... 防衛式 -> 表達式, 表達式, ... end｜、parse(A) -> : if :: is_number(A), :: round(A) == A, :: A >= 0 -> ::: {natural, A}; :: is_number(A) -> ::: {real, A}; :: is_atom(A) -> ::: {word, A}; :: true -> ::: {unknown, A} : end.

案例式｜使用 case ... of ... end 關鍵字，根據一個變數的案例，帶往相對的處理程序。格式為： case 表達式 of 樣式 -> 表達式, 表達式, ... ; 樣式 -> 表達式, 表達式, ... ; ...... 樣式 -> 表達式, 表達式, ... end、樣式之後可接when防衛式。｜、show(A) -> : case A of :: {natural, N} -> ::: io:format("Natural number ~.10B is met.~n", N); :: {real, R} -> ::: io:format("Real number ~f is met.~n", R); :: {word, W} -> ::: io:format("\"~w\" is met.~n", W); :: {unknown, U} -> ::: io:format("Unknown structure ~w.~n", U) : end.

試誤｜使用 try ... catch ... end 關鍵字敘述試誤的情況與結果。格式為： try 表達式 of 樣式 -> 表達式, 表達式, ... ; 樣式 -> 表達式, 表達式, ... ; ...... 樣式 -> 表達式, 表達式, ... catch 樣式(例外) -> 表達式, 表達式, ... ; 樣式(例外) -> 表達式, 表達式, ... ; ...... 樣式(例外) -> 表達式, 表達式, ... after 表達式, 表達式, ... end、不需要使用after段落時，可省略after段落。、樣式之後可接when防衛式。｜(略)

接收訊息｜每個Erlang程式執行時，都可以從自己程序的郵箱中取得由其他程序送到的訊息。可以使用 receive ... end 關鍵字接收訊息，格式為： receive 樣式 -> 表達式, 表達式, ... ; 樣式 -> 表達式, 表達式, ... ; ...... 樣式 -> 表達式, 表達式, ... end、樣式之後可接when防衛式。｜、loop(FromPid, Result) -> : receive :: {FromPid, stop} -> ::: Result; :: {FromPid, Any} -> ::: loop(FromPid, Result) : end.

發送訊息｜Erlang容許向程序傳送訊息。使用 ! 關鍵字，格式為：程序代號 ! 訊息、訊息可以是各種資料格式。訊息資料格式可以是用各種表達式求出的值。｜、Pid = erlang:spawn( : fun -> :: receive ::: X -> X :: end : end) :、以上產生一個程序。、Pid ! {hello, world} :、以上對Pid送出訊息。

列表解析｜列表解析，是提供快速建立列表的語法。語法等同於集合建構式。格式為：、變數(表達式中的元素)｜變數(表達式中的元素) <- 表達式 , 防衛式 : 若無防衛條件，列表解析中不寫防衛式。｜、X｜X <- 1,2,3 : 運算結果為1,2,3

### 內建函數

開源電信平台包括一個Erlang直譯器、一個Erlang編譯器、程序節點通訊協定、CORBA、一個分散式資料庫Mnesia、以及許多程式庫。

內建函數涵蓋了各種方面的功能，涵蓋了系統命令、資料存取、格式轉換、網路通訊、圖形介面、 ... 等。以下列表介紹幾項常用的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 的一種方式：

```erlang
-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(Rest) ->

qsort( X 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最主要的特色是平行導向程式設計，強調多程序平行運作，並且以訊息對彼此溝通。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)),

Pids = spawn(?MODULE, lists:nth(Nth,Funs),)

Nth <- Ns ,

Pid ! ToPid

{Pid, ToPid} <- lists:zip(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訊息的執行結果。

> _ = example:ring_proc(func,func,func).

,,

> P ! stop.

Stop process

stop Stop process

> Stop process

>

### 容錯處理

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、... 等模組，做網路通訊。

## 其他程式設計典範

### 惰性求值

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。支持了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

## 延伸閱讀

- Early history of Erlang by Bjarne Däcker

## 基本資料

- 編程范型：多重典範：函數式、並行
- 發行時間：1986年
- 設計者：喬·阿姆斯特朗、Robert Virding、Mike Williams
- 開發者：愛立信
- 類型系統：動態、強
- 受影響於：Prolog, Smalltalk, PLEX, LISP
- 施影響於：Akka, Clojure, Dart, Elixir, F♯, Opa, Oz, Reia, Rust, Scala
- 文件擴展名：.erl .hrl
- 許可證：Apache許可證2.0（從OTP 18.0開始）、Erlang公共許可證（早期版本）
- wikibooks：Erlang Programming