# 簡介
Erlang是一門被設計用于編寫并發、實時、分布式系統的新語言。
很多年來,并發實時系統的編程技術一直落后于串行應用的編程。當使用C或Pascal進行串行編程已經成為實踐標準時,大多數實時系統的程序員還在倒騰著匯編。如今的實時系統可以使用Ada、Modula2、Occam等為并發編程提供了顯式支持的語言來編寫,或是仍舊使用C這樣缺乏并發結構的語言。
我們對并發的興趣源自于對一些展現出大規模并發的問題的研究。這是實時控制系統的一個典型屬性。Erlang程序員可以顯式指定哪些活動需要由并發進程來展現。這種觀念與Occam、CSP、Concurrent Pascal等語言類似,但與那些并不為了對現實世界的并發進行建模而引入并發的語言不同,這些語言引入并發的目的只是為了將編譯出可在并行處理器上運行的程序以獲得更高的性能。
現今Prolog和ML等語言已經被大范圍用于工業應用之中,并極大地降低了設計、實現和維護應用的成本。我們對Erlang的設計和實現也是為了將并發實時系統編程提高到一個相似的高度。
申明式語法
> Erlang具備申明式的語法,且大部分都無副作用。
并發
> Erlang具備一個使用消息傳遞的基于進程的并發模型。Erlang的并發機制是輕量級的,如進程只占用極少的內存,進程的創建、刪除以及消息傳遞也都只涉及極少量的計算。
實時
> Erlang可用于對相應延遲在毫秒數量級的軟實時系統進行編程。
持續運作
> Erlang具備替換運行時系統代碼的原語,并允許新舊版本的代碼同時執行。這在電話交換機、空中交通控制等“不停機”系統中有極大的用處,這些系統在軟件變更時都不能停機。
健壯
> 在上述系統中,安全性是一個關鍵需求。Erlang具備三種結構來檢測運行時錯誤。這些可用于編寫健壯的系統。
內存管理
> Erlang是一門具備實時垃圾回收機制的符號計算語言。內存在需要時自動分配,在不需要時自動回收。典型的內存管理相關的編程錯誤都不再存在。
分布式
> Erlang沒有內存共享。所有進程間交互都通過異步消息傳遞完成。使用Erlang可以輕易地構建分布式系統。為單處理器編寫的應用不花什么力氣就可以移植到處理器網絡上運行。
集成
> Erlang可以簡單地調用其他語言編寫的程序。通過Erlang的接口系統,這些程序對于程序員來看就好像是用Erlang編寫的一樣。
我們從申明式語言和并發語言中借鑒了大量思想。早期Erlang的語法多半歸功于STRAND,盡管當前的語法讓人覺得像是無類型的ML。其并發模型則與SDL類似。
我們的目標是為健壯的大規模并發工業應用編程提供一種精煉、簡單和高效的語言。因此,出于效率原因,我們放棄了許多現代函數式語言中的特性。Currying、高階函數、延遲求值、ZF comprehension、邏輯變量、deep guards等,增強了申明式編程語言的表達能力,但對于工業控制應用而言,沒有這些特性也不會有什么顯著影響。倒是模式匹配語法的使用和Erlang變量的“單次賦值”屬性,使得我們能夠編寫清晰、短小且可靠的程序。
最初Erlang是邊實現邊設計的,第一個版本是一個使用Prolog編寫的解釋器。與此同時,我們非常幸運地擁有了第一批熱情的用戶群,他們當時正在開發一個新電話交換機的原型。
這便催生了一條極為有效的語言設計途徑。不被使用的構件被拋棄,對于令我們的用戶不得不編寫令人費解的代碼的問題,則引入新的語言構件予以解決。盡管我們經常會對語言進行一些不向下兼容的更改,我們的用戶還是飛速地編寫了成千上萬行的代碼,并積極地鼓動其他人來使用這門語言。他們的努力催生了一種新的電話交換機編程方法,相關的一些內容被發表在[??]和[??]。
第一版基于Prolog的Erlang解釋器很早以前就被編譯型的實現所替代了。其中的一個實現可以免費獲取,并使用非商業許可證。當前的Erlang實現在兼顧速度和輕量級并發的同時滿足了我們的實時性要求。Erlang實現已經被移植到多種操作系統及多種處理器上。
Erlang適用于對很大范圍內的并發應用進行編程。不少工具被開發出來用于輔助Erlang編程,如X Window System的接口、ASN.1編譯器(使用Erlang編寫并生成Erlang代碼)、分析程序生成器、調試器……
## 讀者群
本書面向對實時控制系統感興趣且有一定的編程經驗的人。但并不需要對函數式或邏輯語言有所了解。
本書中的材料與近年來在Ericsson及其全世界范圍內的子公司以及瑞士大學舉辦的多次Erlang課程有關。該課程為期四天,不光展示語言本身,也對Erlang的多種編程范式進行介紹。課程的最后一天通常是一個編程練習,學生們將編寫一個與第??章所描述的類似的電話交換機控制系統,并在一臺實際的交換機上執行!
## 概要
本書被劃分為兩大部分。第一部分“編程”,介紹Erlang語言以及在Erlang編程中常見的一些編程范式。第二部分,“應用”,由一系列完備的章節構成,包含典型Erlang應用的案例分析。
## 編程
第1章是對Erlang的一個介紹性教程。通過一系列示例對語言的一些主要思想予以說明。
第2章介紹串行編程。這里將會介紹模塊系統,這會是我們談及Erlang時的一個基本術語。
第3和第4章包含一系列使用列表和元組進行編程的示例。這里將介紹列表和元組的基本編程技巧。在后續章節中需要用到的一些標準模塊在此也會提及。其中包括實現集合、字典、平衡及非平衡二叉樹等等的模塊。
第5章介紹并發。在串行編程基礎之上添加少量的原語便將Erlang變為一門并發編程語言。我們將介紹用于創建并行進程以及在進程間進行消息傳遞的原語。我們還將介紹為了將進程與一個名稱相關聯而引入的進程注冊機制。
此處將解釋服務器—客戶端模型背后的基本思想。該模型在后續章節中被大量使用,同時也是用于協調多個并行進程間的活動的一種基本編程技術。我們還將介紹可讓我們編寫實時程序的超時。
第6章是對分布式編程的一個概述,解釋了編寫分布式應用的一些動機。我們描述了用于編寫分布式Erlang程序的語言原語并解釋了如何在Erlang節點網絡中排布多組進程。
第7章解釋了Erlang中的錯誤處理機制。我們將Erlang設計用于編寫健壯的應用,語言中包含了三種正交的機制用于完成錯誤檢查。我們認為語言應該在運行時檢測出盡可能多的錯誤并讓程序員負責糾正這些錯誤。
第8章展示了如何使用前一章介紹的錯誤處理原語來構建健壯的容錯系統。我們展示了如何將錯誤的代碼拒之門外,提供了一個容錯的服務器(通過擴展客戶端服務器模型)并展示了如何對計算進行“隔離”以便在出錯時對破壞范圍進行限制。
第9章包含了一系列在本書其他部分未提及的編程思想和技巧。我們在此討論尾遞歸優化。對于希望正確編寫出不間斷運行程序的程序員而言,對該優化的理解是至關重要的。We then introduce references which provide unique unforgetable symbols. 本章之后的兩節描述了如何更改運行時系統的Erlang代碼的細節(編寫不停機系統需要使用這種技術)以及如何將Erlang與使用其他語言編寫的程序對接。之后,我們將介紹用于高效處理大量無類型數據的二進制數據處理、為每個進程提供了可銷毀存儲能力的進程字典,以及作為分布式Erlang核心的網絡內核。最后我們將對執行效率進行討論,并舉例說明如何編寫高效的Erlang代碼。
## 應用
第10章展示了如何使用Erlang編寫一個數據庫。我們從第??章開發的簡單字典模塊和第??章的客戶端—服務器模型開始,由此完成一個簡單的并發數據庫。然后我們將展示如何以組織成多級樹形結構的并行進程來實現該數據庫,以此改善其吞吐量。接著我們加入事務性,以使得多個串行數據庫操作可以表現出原子性。
在這之后,我們為數據庫增加“回滾”機制以允許我們“撤銷”先前的數據庫操作。回滾示例對非破壞性賦值進行了漂亮的展示。
接著我們討論如何讓我們的數據庫能夠容錯。最后,我們展示如何將一個外部數據庫與我們的數據庫集成,并為程序員提供統一的接口。
第11章介紹分布式編程技術。我們展示如何使用Erlang實現多種常見的分布式編程技術,如遠程過程調用、廣播、promises等等。
第12章研究分布式數據問題。許多情況下,運行在不同物理機器上的多個應用希望共享一些公共數據結構。本章描述用于實現分布式系統中的共享數據的各種技術。
第13章是對Erlang操作系統的討論。由于所有的進程管理都在Erlang內部完成,我們對傳統操作系統提供的服務所需甚少。我們在此展現Erlang操作系統中用于完成語言標準分布式任務的主要組件。該操作系統可以作為更專一化的操作系統的基礎以用于某個具體應用之中。
第14章與兩個實時控制問題相關。第一個是著名的電梯控制問題——這里我們將看到將系統建模為一組并行進程提供了一套簡單優雅的解決方案。第二部分討論“進程控制”,此處我們的“進程”是一個衛星。觀測衛星的唯一途徑是分析安裝在衛星上的傳感器所發送的數據。變更衛星行為的唯一途徑是向衛星上的儀器發送指令。盡管這里以衛星控制系統為例,相關技術可以應用于更廣泛的范圍。
第15章是一個小型本地電話交換機的實時控制系統實例。Erlang是Ericsson計算機科學實驗室開發出來的,而Ericsson也是世界上主要電話交換機的生產商之一——簡化電信編程始終都是我們的主要興趣所在!
本章中的示例只是一個“玩具”系統。然而麻雀雖小五臟俱全,它展示了用Erlang構建電信軟件的許多技術。該示例只是那些用于控制復雜電信應用的龐大Erlang程序的小兄弟。這些程序都由數萬行Erlang代碼構成,是本章所描述的各種編程技術的擴展應用。
本章的末尾對SDL做了一個簡短的介紹(SDL被廣泛用于描述電信系統的行為)——我們在此展現了一份SDL規范與實現這份規范的Erlang代碼的一一對應關系。SDL與Erlang之間的概念“鴻溝”很小——這將降低實時系統的設計實現成本。
第16章簡短地介紹了ASN.1并給出了一個從ASN.1到Erlang的交叉編譯器。ASN.1是用于描述通訊協議數據格式的標準。本章展現了ASN.1規范與用于操作ASN.1描述的數據包的Erlang代碼間的相似性。為系統中通訊軟件部分自動產生大部分代碼的能力大大簡化了系統的構建過程。
第17章展示了如何為Erlang應用構建用戶界面。本章展示了兩點:第一,并發進程組如何良好地映射到窗口系統中的一組對象;第二,讓Erlang與其他語言編寫軟件包協同運作。
第18章中我們討論面向對象程序語言的一些主要屬性以及如何在Erlang中予以實現。我們將討論面向對象設計及其Erlang實現之間的關系。