簡介

關於本教學

這裡是「學 Erlang 讓你超棒!」的開始!閱讀本教學應該是您學習 Erlang 的第一步,所以我們來稍微談談它。

Erlang logo

首先,我開始萌生寫這份教學的想法,是在閱讀了 Miran Lipovača 的 「學 Haskell 讓你超棒!(LYAH)」 教學之後;我認為他在讓這門語言變得吸引人,以及讓學習體驗變得友善方面做得非常棒。因為我已經認識他,所以我問了他對於我撰寫 Erlang 版本的書有什麼想法。他很喜歡這個想法,因為他對 Erlang 有些興趣。

所以我就在這裡打字了。當然,我還有其他的動機:我主要覺得這門語言的入門很難(網路上的文件很少,不然就得買書),而且我認為社群會從類似 LYAH 的指南中受益。不太重要的是,我看到人們有時會根據以偏概全的概括來過度讚揚或貶低 Erlang。然後有些人鐵定認為 Erlang 只不過是炒作。如果我想要說服他們別這樣想,我知道他們一開始就不太可能閱讀這篇文章。

因此,本書希望成為一種讓對命令式程式語言(例如 C/C++、Java、Python、Ruby 等)有基本程式設計知識,並且可能(或可能沒有)接觸過函數式程式設計(Haskell、Scala、Erlang、Clojure、OCaml...)的人學習 Erlang 的途徑。我也希望以誠實的方式撰寫這本書,實話實說地推銷 Erlang,並承認它的優缺點。

那麼 Erlang 是什麼呢?

首先,Erlang 是一種函數式程式語言。如果您曾經使用過命令式語言,那麼像是 i++ 這樣的語句對您來說可能很正常;但在函數式程式設計中,這些是不允許的。事實上,嚴格禁止變更任何變數的值!這乍聽之下可能很奇怪,但如果您還記得您的數學課,其實您學的就是這樣

y = 2
x = y + 3
x = 2 + 3
x = 5

如果我加上以下內容

x = 5 + 1
x = x
∴ 5 = 6

您一定會非常困惑。函數式程式設計認可這一點:如果我說 x 是 5,那麼在邏輯上我不能聲稱它也是 6!這是不誠實的。這也是為什麼具有相同參數的函數應該總是傳回相同的結果。

x = add_two_to(3) = 5
∴ x = 5

對於相同的參數,函數總是傳回相同的結果稱為引用透明性。這讓我們可以用 5 來取代 add_two_to(3),因為 3+2 的結果永遠是 5。這表示我們可以將數十個函數串在一起,以解決更複雜的問題,同時確信不會有任何東西損壞。合乎邏輯且乾淨,不是嗎?不過,這存在一個問題

x = today() = 2009/10/22
  -- wait a day --
x = today() = 2009/10/23
x = x
∴ 2009/10/22 = 2009/10/23

噢不!我美麗的等式!它們突然都變錯了!為什麼我的函數每天都傳回不同的結果?

顯然,在某些情況下,打破引用透明性是有用的。Erlang 對函數式程式設計採取了非常務實的方法:遵守其最純粹的原則(引用透明性、避免可變資料等),但在出現實際問題時打破這些原則。

An envelope

現在,我們將 Erlang 定義為一種函數式程式語言,但它也非常強調並行性和高可靠性。為了能夠同時執行數十個任務,Erlang 使用了Actor 模型,而每個 Actor 都是虛擬機器中的一個獨立程序。簡而言之,如果您是 Erlang 世界中的一個 Actor,您將會是一個獨自一人坐在沒有窗戶的黑暗房間裡,等著從信箱接收訊息的人。一旦您收到訊息,您會以特定的方式回應:收到帳單時付款,收到生日卡時回覆「謝謝」信,並忽略您看不懂的信。

Erlang 的 Actor 模型可以想像成一個每個人都獨自坐在自己的房間裡,並且可以執行一些不同任務的世界。每個人都嚴格地透過寫信來溝通,就這樣。雖然這聽起來像是個無聊的生活(也是郵政服務的新時代),但這表示您可以要求許多人為您執行非常特定的任務,而且他們都不會做錯事或犯錯,進而影響其他人的工作;他們甚至可能不知道除了您以外的其他人的存在(這很棒)。

為了擺脫這種比喻,Erlang 強迫您編寫 Actor(程序),這些 Actor 不會與其他程式碼共享任何資訊,除非它們彼此傳遞訊息。所有通訊都是明確、可追溯且安全的。

當我們定義 Erlang 時,我們是在語言層面上這樣做的,但從更廣泛的意義上來說,這並非它的全部:Erlang 也是一個整體的開發環境。程式碼會編譯成位元組碼,並在虛擬機器內執行。因此,Erlang 很像 Java 和有 ADD 的孩子,可以在任何地方執行。標準發行版包含(但不限於)開發工具(編譯器、偵錯器、效能分析器、測試框架)、開放電信平台 (OTP) 框架、網頁伺服器、剖析器產生器,以及 Mnesia 資料庫,這是一個能夠在多個伺服器上自我複製的鍵值儲存系統,支援巢狀交易並讓您儲存任何種類的 Erlang 資料。

VM 和程式庫也讓您可以在不中斷任何程式的情況下更新執行中系統的程式碼,輕鬆地在多台電腦上分配您的程式碼,並以簡單但強大的方式管理錯誤和故障。

A crashed plane

稍後我們將會看到如何使用這些工具中的大多數並實現安全性,但現在,我將告訴您 Erlang 中一個相關的通用策略:讓它崩潰。不是像一架載著數十名乘客死亡的飛機那樣,而是更像一個底下有安全網的走鋼索的人。雖然您應該避免犯錯,但在大多數情況下,您不需要檢查每種類型或錯誤狀況。

Erlang 從錯誤中復原、使用 Actor 組織程式碼,以及透過分佈和並行性擴展的能力聽起來都很棒,這將我們帶到下一節…

別喝太多 Kool-Aid

書中可能會有很多像這樣的小黃橘色區塊(當您看到它們時,您就會認出它們)。Erlang 目前由於熱情的談論而越來越受歡迎,這可能會讓大家相信它的能力超出實際。這些提醒將會在那裡幫助您腳踏實地,如果您是那些過度熱情的學習者之一。

第一個案例與 Erlang 由於其輕量級程序而具有的大規模擴展能力有關。Erlang 程序確實非常輕量級:您可以同時擁有數十萬個程序,但這並不表示您必須這樣使用它,僅僅因為您可以。例如,建立一個射擊遊戲,其中包含包括子彈在內的所有東西都是它自己的 Actor 是瘋狂的。使用像這樣的遊戲您唯一會射擊的東西就是您自己的腳。從 Actor 向 Actor 發送訊息仍然存在一些小成本,而且如果您過度劃分任務,您將會讓事情變慢

當我們學到足以真正擔心這個問題的程度時,我將更深入地介紹這一點,但請記住,隨機地將並行性應用於問題不足以使其快速運作。別難過;有時候使用數百個程序既有可能也有用!只是不是所有時候都會發生。

人們也說 Erlang 能夠以與您的電腦擁有的核心數量成正比的方式進行擴展,但這通常不是真的:糟糕的圖表:速度 vs 核心:它只是擴展! 這是可能的,但大多數問題的行為方式並不會讓您同時執行所有事情。

還需要記住另一件事:雖然 Erlang 在某些方面做得很好,但從技術上來說,仍然有可能從其他語言獲得相同的結果。反之亦然;根據問題的需求評估每個問題,並根據要解決的問題選擇正確的工具。Erlang 並非萬靈丹,而且在影像和訊號處理、作業系統裝置驅動程式等方面的表現特別差,而在大型伺服器軟體(即:佇列、Map-Reduce)、結合其他語言進行一些提升、更高層級的協定實作等方面的表現會很出色。中間的區域將取決於您。您不一定需要將自己局限於使用 Erlang 的伺服器軟體:曾經有人做過出乎意料和令人驚訝的事情。一個例子是 IANO,這是一個由 UNICT 團隊創建的機器人,它使用 Erlang 進行人工智慧,並在 2009 年的 Eurobot 競賽中獲得銀牌。另一個例子是 Wings 3D,這是一個用 Erlang 編寫的開放原始碼 3D 建模器(但不是渲染器),因此是跨平台的。

您需要投入的內容

您只需要一個文字編輯器和 Erlang 環境即可開始使用。您可以從Erlang 官方網站取得原始碼和 Windows 二進位檔。我不會詳細說明安裝細節,但對於 Windows,只需下載並執行二進位檔案即可。別忘了將您的 Erlang 目錄新增到 PATH 系統變數,以便能夠從命令列存取它。

在基於 Debian 的 Linux 發行版上,您應該可以透過執行 $ apt-get install erlang 來安裝套件。在 Fedora 上(如果您已安裝 'yum'),您可以透過輸入 # yum install erlang 來達到相同的目的。然而,這些存放庫通常包含過時的 Erlang 套件版本;使用過時的版本可能會導致您在本教學中獲得的內容與某些應用程式的效能之間存在一些差異。因此,我鼓勵您從原始碼編譯。請參閱套件中的 README 檔案和 Google,以取得您需要的所有安裝詳細資訊,它們會做得比我更好。

在 FreeBSD 上,您可以選擇許多選項。如果您使用 portmaster,您可以執行 portmaster lang/erlang。對於標準 Port,它應該是 cd /usr/ports/lang/erlang; make install clean。最後,如果您想要使用套件,請執行 pkg_add -rv erlang

如果您使用 OSX,您可以透過 $ brew install erlang(使用 Homebrew)或執行 $ port install erlang(如果您偏好 MacPorts)來安裝 Erlang。

或者,Erlang Solutions Ltd. 提供適用於所有主要作業系統的套件,這些套件通常運作良好(選擇「標準」發行版)。

注意:在撰寫本文時,我使用的是 Erlang R13B+ 版本,但為了獲得最佳結果,您應該使用較新的版本。

哪裡可以獲得協助

有幾個地方您可以獲得協助。如果您使用 Linux,您可以存取 man 頁面以取得良好的技術文件。Erlang 有一個清單模組(我們很快就會看到):要取得有關清單的文件,只需輸入 $ erl -man lists 即可。

在 Windows 上,安裝應該包含 HTML 文件。您可以隨時從Erlang 官方網站下載它,或參閱更簡潔的替代網站之一。

一旦您覺得需要將所有內容整理乾淨時,可以在這裡找到良好的程式設計實務。本書中的程式碼也會嘗試遵循這些準則。

現在,有時候光取得技術細節是不夠的。當這種情況發生時,我通常會求助於兩個主要來源:官方郵件列表(你應該追蹤它以學習大量知識)以及 #erlangirc.freenode.net 上的頻道。

喔,如果你是喜歡食譜和現成配方的那種人,trapexit 就是你要找的地方。他們也將郵件列表鏡像為論壇和一般維基,這總是很有幫助的。