Erlang

Erlang（）是一種通用的-{zh-hans:并发;zh-hant:平行導向;}-函数式-{zh-hans:程序设计语言;zh-hant:程式語言;}-。Erlang也可以指Erlang/OTP的通稱，開源電信平台（OTP）是Erlang的常用執行環境及一系列標準元件。

Erlang 執行環境為專有以下要求的系統設計：
 分散式運算
 高故障容許度
 軟性即時運算
 高可用性、不停運作的應用
 熱插拔，可以修改程式而不必停機

Erlang是運作於虛擬機的-{zh-hans:解释型语言;zh-hant:直譯式語言;}-，但是現在也包含有烏普薩拉大學高性能Erlang計劃（HiPE）開發的原生程式碼編譯器，自R11B-4版本開始，Erlang也支持-{zh-hans:脚本方式执行;zh-hant:腳本直譯器;}-。在編程範型上，Erlang屬於多重典範程式語言，涵蓋函數式、-{zh-hans:并行;zh-hant:平行式;}-及-{zh-hans:分布式;zh-hant:分散式;}-。循序執行的Erlang是一个及早求值, 單次賦值和-{zh-hans:动态类型;zh-hant:動態資料形態;}-的函數式程式語言。

它由喬·阿姆斯特朗（Joe Armstrong）在瑞典電信設備製造商愛立信所轄的電腦科學研究室開發，目的是創造一種可以應付大規模并發活動的-{zh-hans:程序设计语言;zh-hant:程式語言;}-和執行環境。Erlang於1987年釋出正式版本，最早是愛立信擁有的私有軟體，經過十年的發展，於1998年發表開放源碼版本。

 開發及演變歷史 
Erlang得名於丹麥數學家及統計學家Agner Krarup Erlang，同時Erlang還可以表示Ericsson Language。Erlang語言由瑞典愛立信電信公司的喬·阿姆斯特朗開始設計，開始於公元一九八零年代。最初是以Prolog-{zh-hans:程序设计语言; zh-hant:程式語言;}-為基礎，幾度改版之後，改成以Joe's Abstract Machine為基礎的獨立語言執行環境。雖然語言風格仍與Prolog相近，不過因Erlang語言設計的走向，Erlang成為具备函數語言特色的-{zh-hans:程序设计语言; zh-hant:程式語言;}-見Coders At Work一書對Joe Armstrong的口述記錄。。

 發行版本 
1998年起，Erlang發布開放源碼版本，稱為開源電信平台。開源電信平台採用修改過的Mozilla公共許可證協議發放，同時爱立信仍然提供商業版本的技術支持。目前，Erlang最大的商業用户是爱立信，其他知名用户有北電網路、-{zh-hans:亚马逊; zh-hant:亞瑪遜}-以及T-Mobile等 “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等。

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

 語言構成 
Erlang-{zh-hans:程序;zh-hant:程式;}-結構以函數定義為主。函數是一組將輸入分別對應到輸出的規則，對應方式遵守數學函數的慣例。此外，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] 二進位資料 以左邊 << 、右邊 >> 符號，包含由位元語法表示的資料。 <<"Hello, World!">>
 <<65:8,66:8,67:8>> 函數識別項 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'}
 [H|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, [Any|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 的一種方式：譯自官網 https://www.erlang.org/faq/getting_started.html 
-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最主要的特色是平行導向程式設計，強調多程序平行運作，並且以訊息對彼此溝通。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、... 等模組，做網路通訊參考分散式Erlang ， https://www.erlang.org/doc/reference_manual/distributed.html 。

 其他程式設計典範 
 惰性求值 
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及FreeBSDErlang及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









 外部連結 
Erlang開放源碼版本
Erlang愛立信授權版本
因應軟體錯誤建構可靠的分散式系統 

Erlang教學

Category:程序设计语言
Category:并发编程语言
Category:函数式编程语言
Category:宣告式編程語言
Category:模式匹配编程语言
Category:Erlang
Category:愛立信
Category:1986年建立的程式語言