← 所有文章

工程哲學:Roberto Ierusalimschy

Roberto Ierusalimschy,Lua 的創造者

重點摘要

  • 他設計的這門腳本語言,藏身於您日常接觸的大量軟體之中。 Roberto Ierusalimschy 主導了 Lua 的設計,這門語言於 1993 年誕生於 PUC-Rio 的 Tecgraf 實驗室,由他與 Luiz Henrique de Figueiredo、Waldemar Celes 共同創造。它驅動著《魔獸世界》的遊戲邏輯、《Roblox》(透過其 Luau 方言)、《Dota 2》與《Garry’s Mod》,為 Redisnginx(透過 OpenResty)編寫腳本,支撐 Adobe LightroomWireshark 的運作,甚至嵌入到底層連作業系統都沒有的機器人裝置之中。127
  • 提供機制,而非政策。 Lua 的定義性抉擇是一種拒絕——它不附帶類別系統、物件模型,也不附帶任何典範。它只給您少數幾個強大而通用的機制(table、metatable、coroutine),讓您在其上構建自己的抽象。「Lua 不會把任何物件或類別模型強加於程式設計師身上,」設計者們寫道;他們選擇「提供靈活的機制」,讓您構建出最適合應用情境的任何模型。3
  • 小巧是一項特性,而非侷限。 其參考實作既精簡又乾淨——Lua 5.1 的原始碼約為 17,000 行 C 程式碼,整套發行版可塞進一張軟碟,編譯出的直譯器大約只有 143 KB。多數腳本語言要大上一個數量級;Lua 之所以維持小巧,正是因為它生來就是要被嵌入,而簡單正是讓小巧、快速的實作得以成立的關鍵。3
  • 可攜性與可嵌入性從第一天起就是設計目標。 Lua 以「乾淨的 C」寫成——也就是 C 與 C++ 的交集——並且「在多數平台上開箱即可編譯」,從 Linux、Windows 到掌上型裝置與微控制器無不如此。一套定義良好的 C API 讓宿主程式得以完全掌控並擴充它,這正是遊戲產業將其奉為近乎標準的原因。34

核心原則

「我們不想把 Lua 變成一門物件導向語言,因為我們不想為 Lua 固定下某一種程式設計典範……Lua 不會把任何物件或類別模型強加於程式設計師身上。相反地……我們決定提供靈活的機制,讓程式設計師能夠構建出最適合應用情境的任何模型。」——Roberto Ierusalimschy、Luiz Henrique de Figueiredo 與 Waldemar Celes,《The Evolution of Lua3

多數語言設計是政策的層層堆積。一個團隊決定物件應該以這種方式運作、錯誤處理應該長成那種樣子、並行意味著執行緒、async 或 actor——然後把這些決定烤進語言裡,於是每一支用它寫成的程式都繼承了這些抉擇。這些決定通常都合情合理。問題在於,它們終究是決定,由無法預知您應用情境的人們,一次性地、替所有人作出。Ierusalimschy 的直覺走向相反的方向。Lua 不替您決定,而是交給您一小組通用機制,然後讓開,好讓您構建出問題真正需要的政策。3

最清楚的例子就是物件導向。在 1990 年代初,當物件導向程式設計正處於聲勢的頂峰時,使用者不斷催促 Lua 團隊加入類別與繼承。他們拒絕了——不是因為 OOP 有錯,而是因為對一門注定要被嵌入到千差萬別的應用之中的語言來說,固定下某一種模型才是錯的。他們的理由是,物件與類別「若有需要,都可以用 table 來實作」,因為一個 table 既能容納資料也能容納方法,而函式則是一等公民。3 於是,他們沒有打造物件系統,而是構建了可擴充的語意——一種讓您得以介入 table 行為方式的機制——並讓使用者自行組裝出繼承、預設值、唯讀視圖,乃至完整的類別階層。「可擴充的語意已成為 Lua 的招牌特色,」他們寫道,而且「直到今天我們都不曾改變心意。」3

這份拒絕之所以負擔得起,全因有另外三項承諾與之相伴而行。簡單——語言維持得夠小,使得機制易於理解、實作得以正確。以小巧為特性——整套參考實作約為 17,000 行乾淨的 C 程式碼,小到把 Lua 加進一個應用「不會讓它變得臃腫」。3 還有可攜性——以 C 與 C++ 的交集來書寫,意味著同一份原始碼從超級電腦到感測器處處皆可編譯。3 給人們幾根銳利而通用的操縱桿,而不是一整櫃預先決定好的按鈕,並且讓整件東西小到隨處都能攜帶。 這就是那項原則,而 Lua 中其餘的一切都是它的衍生結果。

背景脈絡

Roberto Ierusalimschy 於 1960 年 5 月 21 日生於里約熱內盧,他的整個職涯都緊鄰著同一所機構——里約熱內盧天主教大學(PUC-Rio),他於 1990 年在此取得電腦科學博士學位,如今則是該校的資訊學正教授。他曾在滑鐵盧大學做過博士後研究,也曾到史丹佛擔任客座教授,但 PUC-Rio 才是他的歸屬,而 Lua 的故事與那裡的某個特定實驗室密不可分。5

那個實驗室就是 Tecgraf,即電腦圖學技術小組,成立於 1987 年,宗旨是為工業客戶打造軟體工具——其中規模最大的客戶之一,過去是、如今仍是巴西的石油公司 Petrobras。3 Lua 的緣起,有一部分是關於巴西貿易政策的故事。從 1977 年直到 1992 年,巴西對電腦硬體與軟體維持著強硬的貿易壁壘政策——所謂的「市場保留」——其背後是一種民族主義式的信念,認為這個國家能夠、也應當自行打造這些東西。在那樣的氛圍下,Tecgraf 的客戶「無論在政治上還是財務上,都負擔不起從國外採購客製化軟體」。購買外國工具意味著一道「繁瑣的官僚程序,得證明他們的需求無法由巴西本土公司滿足」。這些限制,再加上巴西與其他研究中心之間在地理上的隔絕,「促使 Tecgraf 從零開始實作自己所需的基本工具」。3 按設計者自己的說法,Lua 是「唯一一門誕生於開發中國家、卻達致全球影響力的語言」。3

在 Lua 之前,曾有兩門小語言,都是為 Petrobras 而打造。DEL——「資料輸入語言」——用來產生圖形化前端,好讓工程師能透過點選圖表來輸入模擬器參數,而不必逐欄編輯一堆數字。3 SOL——「Simple Object Language」(簡單物件語言)——則是一門用於報表產生器的設定語言,其型別宣告語法受到 BibTeX 的影響。3 到了 1993 年初,兩者都已超出各自原本的設計範圍;DEL 的使用者想要真正的控制流程,而 SOL 則需要程序化的能力。1993 年年中,Ierusalimschy、de Figueiredo 與 Celes 得出結論:這兩者可以由單一一門更強大的語言取而代之——Lua 團隊由此誕生。這個名字是個流傳下來的小玩笑。SOL 在葡萄牙語中意為「太陽」;Tecgraf 的一位朋友 Carlos Henrique Levy 建議把這門後繼語言取名為 「Lua」——葡萄牙語中的「月亮」3 到了 1993 年 7 月,Waldemar Celes 完成了第一版實作,那是一個由 Ierusalimschy 指導的課程專案,遵循著極限程式設計「能跑得起來的最簡單做法」這條信條。3

作品

table 與 metatable:一種資料結構,一個機制

從 table 講起吧,因為它就是整門語言的縮影。Lua 只提供單一一種資料結構化機制——table,這是它對關聯陣列的稱呼——而這一種結構就承擔起了紀錄、陣列、集合、串列、模組與物件的全部工作。3「雖然多數腳本語言都提供關聯陣列,」設計者指出,「但沒有任何其他語言讓關聯陣列扮演如此核心的角色。」3 一筆紀錄是以欄位名稱為鍵的 table;一個陣列是以整數為鍵的 table;一個物件則是恰好同時容納資料與方法的 table。一個機制,多種用途——這正是「提供機制,而非政策」這份賭注落實到資料上的樣貌。

讓 table 變得可程式化的那根操縱桿,就是 metatable。一般情況下,查找一個 table 沒有的鍵會回傳 nil。但您可以為一個 table 賦予一份 metatable——第二個 table,用來描述第一個在不尋常情境下應當如何行為。其中最重要的項目是 __index:當查找落空時,Lua 會去查詢該 metatable 的 __index,而它可以指向另一個 table,接著到那裡去搜尋。把這些串接起來,您就得到了繼承——純粹由 table 與單一次重導向構築而成。同一個機制,在不同的 metamethod 之下,還能給您運算子多載、預設值、唯讀代理與惰性欄位。這當中沒有一樣是一般意義上的語言特性——它全都是同一個機制,只是用在不同的形態上。3

這個機制並非一開始就完整成形——它的演化本身就是一堂關於克制的課。它始於 Lua 2.1(1995 年)的「fallback」:當某個操作被施加在「錯誤」種類的值上時,Lua 會呼叫這些掛鉤,好讓程式設計師決定接下來會發生什麼。3 table 索引的 fallback 讓 userdata 與其他值得以「表現得像 table 一樣」,從而支援「多種形式的繼承(透過委派)」。3 fallback 是全域性的——每個事件只有一個掛鉤——這使得它們難以在不同函式庫之間共用,於是 Lua 3.0(1997 年)以每型別各有的「tag method」取而代之,而 Lua 5.0(2003 年)則把一切統合進 metatable 與 metamethod,也就是 Lua 沿用至今的形式。(「metatable」一詞由 Rici Lake 於 2001 年提出。)3 每一步都是在把機制變得更通用,而非堆疊上新的特性——這正是讓這門語言始終拒絕附帶類別系統的同一種直覺。

可嵌入性、C API,以及遊戲為何採用 Lua

Lua 其實並不打算當一門獨立的語言。設計者稱它為一門 「可擴充的擴充語言」——說它是擴充語言,是因為它透過設定與腳本來擴充一個宿主應用;說它可擴充,則是因為它反過來又能以 C 函式來加以擴充。3 這當中的樞紐,是一套定義良好的 C API,它「讓 Lua 程式碼與外部程式碼之間得以完整溝通」,並圍繞著一套乾淨的堆疊隱喻而建,用來在 Lua 與宿主之間來回傳遞值。這套 API 不僅讓 Lua 得以與 C、C++ 接合,更透過它們進一步與 Fortran、Java、C# 及其他種種語言相連。3

回報在遊戲領域到來,而這個故事很具體。1997 年 1 月,LucasArts 冒險遊戲《Grim Fandango》的首席程式設計師 Bret Mogilefsky 告訴 Lua 團隊,他已用 Lua 取代了該遊戲自製的腳本語言,而且「這款遊戲極其大量的部分都是用 Lua 寫成的」。3 Mogilefsky 在一場遊戲開發者大會的圓桌論壇上談及此事,自此「Lua 便在遊戲開發者之間口耳相傳,成為遊戲產業中一項確確實實具有市場價值的技能」。3 這份契合是結構性的。遊戲引擎正是那種能從嵌入式腳本層獲益的宿主——粗重的活兒(渲染、物理)留在快速的 C++ 裡,而遊戲邏輯、任務與行為則活在小巧的 Lua 腳本中,讓設計師得以編輯並重新載入,無須重新編譯引擎。小巧、快速、可攜、可嵌入,恰恰正是一款遊戲所需要的特質,而 Lua 從第一版起就是為此而打造的。34

coroutine,以及一套小巧而快速的實作

第三個偉大的機制是 coroutine——而它就像 OOP 一樣,是這個團隊對某項政策的刻意拒絕。整個 1990 年代後期,使用者一再催促加入多執行緒,而顯而易見的做法就是採用標準的搶佔式、共享記憶體執行緒模型。Lua 團隊婉拒了,理由有二:在 C 中實作搶佔式執行緒需要「並非 ANSI C 一部分」的原語,而這會破壞 Lua 的可攜性;更根本的是,「我們當時並不(如今依然不)相信那套標準的多執行緒模型」,因為「在一門連 ‘a=a+1’ 都不具確定性的語言裡,沒有人能寫出正確的程式」。3 於是,他們沒有提供執行緒,而是在 Lua 5.0(2003 年)中提供了 coroutine:一種用於協作式、非搶佔式多工的機制,函式可以將自己暫停,稍後再從它離開之處原封不動地恢復執行。3 coroutine 給您並行的表達力——產生器、協作式排程器、狀態機——卻沒有那種讓共享記憶體執行緒如此難以駕馭的不確定性。再一次,提供的是機制,而非政策。

支撐這一切的,是一套之所以快速正因為它小巧的實作。Lua 的虛擬機在 Lua 4.0 之前都是基於堆疊的;到了 Lua 5.0,它變成了基於暫存器的,這給了程式碼產生器更大的最佳化空間,並削減了一支典型程式所執行的 VM 指令數量。設計者指出,「Lua 5.0 的虛擬機是第一套獲得廣泛使用的、基於暫存器的虛擬機」。3 記憶體則由一套增量式垃圾回收器(於 Lua 5.1 引入)來管理,它以小步前進的方式工作,而非長時間地全域暫停——這對遊戲的即時迴圈至關重要。3 獨立的基準測試把 Lua 列為直譯式腳本語言中最快的一群,快到按設計者的說法,「Adobe Lightroom 超過 40% 是用 Lua 寫成的」,約莫 100,000 行之多。3

Lua 程式語言

Lua 的觸及範圍:從《魔獸世界》到一具沒有作業系統的機器人

把這一切加總起來,Lua 成了一大片軟體中那看不見的腳本層。在遊戲領域,《魔獸世界》把它整個介面都開放給 Lua,好讓玩家能撰寫附加元件;《Roblox》打造了 Luau——一種 Lua 方言——作為數以百萬計的年輕創作者學習寫程式時所用的語言;《Dota 2》、《Crysis》與《Garry’s Mod》也都嵌入了它。1 在遊戲之外,Redis 在資料庫內部原子性地執行 Lua 腳本;nginx 透過 OpenResty 發行版,用 Lua 來為這台網頁伺服器本身編寫程式;Adobe LightroomWireshark 有相當大的部分建構於它之上;Neovim 採用 Lua 作為其一等公民的設定與外掛語言。1 而正因為這套直譯器小巧又可攜,Lua 得以伸進那些幾乎一無所有的硬體之中——設計者講述了 Crazy Ivan 的故事,這具贏得 RoboCup 冠軍的機器人,其「大腦」是讓 Lua「直接跑在一顆 Motorola Coldfire 5206e 處理器上,底下沒有任何作業系統;換句話說,Lua 就是那套作業系統」。7 一門小巧的語言,在貿易限制之下誕生於里約的一間實驗室,最終卻無所不在——因為它幾乎一無所求,卻把構築其餘一切所需的操縱桿交到了您手上。

方法

橫向讀過 DEL、SOL、metatable、coroutine,以及三十年來拒絕讓語言臃腫的歷程,同樣的招式一再重現。Ierusalimschy 的方法與其說是一句口號,不如說是一組始終不渝的承諾。

交付機制,而非政策。 那項定義性的習慣,就是提供一根通用的操縱桿,並拒絕去決定它必須如何被使用。沒有內建的類別系統,沒有固定的並行模型——只有 table、metatable 與 coroutine,您再從中構築出應用所需的任何東西。這個普遍的教訓遠遠超越語言設計而可資借鏡:最耐久的工具,正是那些賦予能力卻不替解法定下形狀的工具。它與 Guido van Rossum 的「做一件事應有一種顯而易見的方式」恰好相反,而這份對比正是重點所在——兩者都自成一格、各臻圓融,而看清您的工具該體現哪一種哲學,才是真正要作的那個決定。3

讓它小到既能保持正確,又能隨處攜帶。 Lua 的參考實作約為 17,000 行乾淨的 C 程式碼,比其他腳本語言小上一個數量級,而那份小巧是一項刻意為之的特性——正是它讓這門語言得以嵌入、可攜,並值得信賴。其中的紀律,是不斷地刪減,直到再拿掉一樣東西它就會壞掉為止,這使 Lua 成了 Sophie Wilson 在 ARM 中那份冷酷極簡主義的軟體鏡像——剝除到只剩承重的本質,效率便自然而然地隨之而來。它是落實到語言執行環境層級的 最小可敬產品3

抵抗別人向您索求的那個特性,直到您找出它底下的那個機制。 當使用者要求物件時,Lua 給了他們可擴充的語意;當他們要求執行緒時,它給了他們 coroutine。每一次,團隊都婉拒了那項具體的政策,轉而交付出更通用的機制,讓使用者自行構築政策——而且至關重要的是,多年之後也不曾改變心意。3 這正是把 證據門檻套用到功能請求上:不要因為有人開口要就把東西加進去;先弄清楚它所解決的問題,再看看您手上既有的某個機制能不能解決它。

通則化,而非堆積。 metatable 並非一開始就完整成形——它從 fallback 長成 tag method、再長成 metamethod,而每一步都是用一個更通用的機制取代前一個機制,而非在旁邊硬栓上一個新特性。3 這個教訓在於:以統合的方式來演化,而非以堆疊的方式,如此語言才會在維持同等大小的同時變得更有能力——這正是 Thompson 與 Ritchie 以小巧、可組合的零件構築 Unix 時所用的同一種「以簡馭繁」之道。

讓約束來設計這件工具。 Lua 之所以存在,是因為巴西的貿易壁壘逼得 Tecgraf 不得不自行打造軟體;而它之所以可攜,則是因為這間實驗室的客戶運行著「一批極為多樣的電腦平台」。3 Ierusalimschy 沒有把那些約束當成包袱,反而讓它們驅策設計,朝著比一個資源充裕的團隊大概會打造出來的更小、更乾淨、更可攜的方向前進——這個教訓是:稀缺,若認真看待,是一件設計工具,而非一句辯解。3

影響鏈

是誰形塑了他

Scheme 與 Lisp 傳統。 設計者明言「Scheme 對 Lua 的影響逐漸加深」,成了「一個靈感來源,尤其表現在匿名函式與完整的語彙作用域的引入上」。3 一如 Scheme,Lua 是動態型別的,把函式當作尋常的一等公民來對待,並讓核心維持小巧——其信念是,一門語言可以憑藉精簡而非龐大來成就強大。(形塑性影響)

DEL 與 SOL,那兩門小語言。 Lua 並非從理論中迸發而出;它生長自為 Petrobras 打造的兩門領域特定語言。SOL 貢獻了用來描述資料的 table 建構式語法,而兩者的經驗則教會了團隊:「複雜應用的大部分,都能用可嵌入的腳本語言來編寫」——按他們的話說,Lua 的誕生正是奠基於這份體悟之上。3(直接影響)

巴西的市場保留。 那道從 1977 年延續到 1992 年的貿易壁壘,是一個出人意料卻貨真價實的影響:它正是 Tecgraf 之所以會自行打造工具的原因,而其客戶平台的多樣性,則是可攜性之所以成為第一要務的設計目標的原因。是政策造就了這門語言。(形塑性影響)

他形塑了誰

遊戲產業的腳本層。 自《Grim Fandango》以降,Lua 成了嵌入遊戲邏輯時近乎預設的選擇,而它所普及的那套模式——以 C++ 寫成的快速引擎、活在嵌入式腳本中的可編輯行為——如今已是業界的標準做法。Roblox 的 Luau 已教會了整整一代孩子用一種 Lua 方言來寫程式。(定義領域的影響)

嵌入式與系統軟體。 Redis、nginx/OpenResty、Wireshark、Neovim 以及數不清的裝置,採用 Lua 作為腳本層,正是因為它索求得如此之少。鮮有語言能從一個資料庫,一路觸及到一台網路分析器,再到一具跑在裸機上的機器人。

珍視小巧的語言設計者。 Lua 矗立在那裡,作為一個運作中的明證:一個小巧、不偏袒任何典範的核心,能在嵌入這個利基領域裡勝過龐大而立場鮮明的語言——這個論點迴盪在自那以後的每一項極簡執行環境、每一種「機制重於框架」的設計之中。

貫穿線

Ierusalimschy 坐落在本系列那場關於一件工具該替您決定多少的長久論辯的一端。Guido van Rossum 把 Python 建立在「做一件事應有一種顯而易見的方式」之上,並附帶了全套電池——這門語言有它的主張,順著它走就是阻力最小的那條路。Bjarne Stroustrup 把 C++ 打造得豐富到幾乎能表達任何典範,並以體積與複雜度為這份豐富付出代價。Ierusalimschy 走上了與兩者都相反的道路:幾乎不附帶任何政策、幾乎沒有任何特性,只有寥寥幾個通用機制與一套 17,000 行的執行環境,剩下的就讓使用者自己去構築。他是 Sophie Wilson 的軟體鏡像,後者的 ARM 之所以勝出,靠的正是被剝除到不滿 25,000 顆電晶體——Lua 就是那份冷酷小巧在 C 中的化身,而一如 ARM 那意外得來的低功耗,它的小巧最終竟成了讓它得以征服一個無人為它設計過的領域(嵌入)的那樣東西。當 van Rossum 說這就是那條顯而易見的路、Stroustrup 說這裡有每一條路時,Ierusalimschy 說的是:這裡是那些操縱桿——您決定要構築什麼,而我會讓整件東西小到隨處都能攜帶。(系列橋接)

我從中汲取的

我從 Ierusalimschy 那裡留下的教訓是:您能交給一個人的最強大之物,是機制,而非政策。 當您打造一件工具時,總會忍不住想把自己對它該如何被使用的主張烤進去——交付那套類別系統、那個框架、那唯一一條受祝福的工作流程。Lua 的整段歷程都是一個論證:相反的做法才更經得起歲月。正因為拒絕固定下一套物件模型、轉而交付出 metatable,這門語言才讓使用者構築出了其設計者從未想像過的繼承機制,用在他們從未預料到的遊戲、資料庫與編輯器之中。如今當我打造某樣東西時,我向 Lua 借來的問題是:我交付的究竟是一個決定,還是一份能力——因為決定服務的是我今天看得見的那些情況,而能力服務的是我看不見的那些。

第二個教訓是:小巧不是您勉強容忍的一道約束——它是您加以守護的一項特性。 在三十年的使用者壓力之下,要讓 Lua 長成一門帶有 class 關鍵字、帶有執行緒函式庫、帶有一套包辦一切的標準框架的龐大語言,原本是再容易不過的事。團隊拒絕了,而這份拒絕正是 Lua 之所以能塞進一張軟碟、處處皆可編譯、並嵌入一具機器人裸機大腦的原因。保持小巧的那份紀律——通則化而非堆積,在找出底下那個機制之前都婉拒那個特性——比起增添的紀律要更艱難,也遠為珍貴。這是把 品質是唯一的變數讀作克制:那件恰到好處的小東西,經數十年捍衛之後,便成了讓其餘一切都得以立足其上的基礎建設。

常見問題

Roberto Ierusalimschy 是誰,他創造了什麼?

Roberto Ierusalimschy 是一位巴西電腦科學家,1960 年生於里約熱內盧,現為 PUC-Rio 的資訊學正教授。他是 Lua 的首席設計者,這門小巧、快速、可嵌入的腳本語言,是他於 1993 年在 PUC-Rio 的 Tecgraf 實驗室與 Luiz Henrique de Figueiredo、Waldemar Celes 共同創造的。他也是《Programming in Lua》一書的作者、模式比對函式庫 LPeg 的創造者,並合著了這門語言的主要歷史文獻《The Evolution of Lua》。356

在 Lua 裡,「提供機制,而非政策」是什麼意思?

它意味著 Lua 給您少數幾個強大而通用的機制,而非強加固定的決定。最清楚的例子就是物件導向:Lua 沒有內建的類別系統。它提供的是 table(既能容納資料也能容納方法)與 metatable(讓您得以客製一個 table 的行為方式),而繼承、類別或任何其他物件模型,都由您自己構築。設計者寫道,「Lua 不會把任何物件或類別模型強加於程式設計師身上」,並選擇轉而「提供靈活的機制」——這是他們自 1993 年以來始終堅守的立場。3

Lua 為何在遊戲與嵌入式系統中如此廣為使用?

因為它從一開始就被設計得小巧、快速、可攜,且易於嵌入。其參考實作約為 17,000 行乾淨的 ANSI C,幾乎處處皆可編譯,編譯出的直譯器大約只有 143 KB,而一套定義良好的 C API 讓宿主程式得以完全掌控它。那樣的特質正是一具遊戲引擎或一台嵌入式裝置所需要的——粗重的活兒交給 C/C++,可編輯的邏輯活在小巧的腳本裡——這也是它之所以為《魔獸世界》、《Roblox》(透過 Luau)、Redis、nginx/OpenResty、Adobe Lightroom,乃至底層連裸機機器人都編寫腳本的原因。137

「Lua」這個名字從何而來?

Lua 在葡萄牙語中意為「月亮」。它被命名為一門早先 Tecgraf 語言的後繼者,那門語言名為 SOL——「Simple Object Language」(簡單物件語言),同時在葡萄牙語中意為「太陽」。Tecgraf 的一位同事 Carlos Henrique Levy 為這門新語言建議了「Lua」這個名字,完成了從太陽到月亮的承接。整個專案是從兩門小語言——DEL 與 SOL——生長出來的,它們都是為巴西石油公司 Petrobras 而打造。3


來源


  1. 〈Lua(程式語言)〉, Wikipedia。Lua 於 1993 年由 Roberto Ierusalimschy、Luiz Henrique de Figueiredo 與 Waldemar Celes 在巴西里約熱內盧天主教大學(PUC-Rio)的電腦圖學技術小組(Tecgraf)創造;以 ANSI C 實作,採 MIT 授權,自 Lua 5.0 起採用基於暫存器的虛擬機,具備垃圾回收、coroutine 與一等函式。近期的參考實作仍維持小巧(該文指出 Lua 5.5.0 約由 32,000 行 C 程式碼構成)。有文獻記載的使用者包括遊戲《魔獸世界》、《Roblox》(其開發了 Luau,一種 Lua 衍生語言)、《Dota 2》、《Crysis》與《Garry’s Mod》,以及非遊戲軟體如 Redis、nginx(透過 OpenResty)、Adobe Lightroom、Wireshark 與 Neovim。 

  2. 〈Roberto Ierusalimschy: Known for Lua Programming Language〉, machaddr(傳記側寫)。概述 Ierusalimschy 作為 Lua 的創造者與首席架構師的角色,該語言由他與 Luiz Henrique de Figueiredo、Waldemar Celes 在 PUC-Rio 開發,於 1993 年首次發布;提及 Lua 在包括《魔獸世界》與 Adobe Lightroom 等軟體中的全球性使用、他對《Programming in Lua》一書的著述,以及他對 LPeg 函式庫的創造。 

  3. Roberto Ierusalimschy、Luiz Henrique de Figueiredo 與 Waldemar Celes,〈The Evolution of Lua〉, Proceedings of the Third ACM SIGPLAN Conference on the History of Programming Languages(HOPL III),2007 年。第一手來源。「Lua 是一門誕生於 1993 年 PUC-Rio 的腳本語言。」「從一開始,Lua 就被設計得簡單、小巧、可攜、快速,並易於嵌入到應用之中。」單一的資料結構:「它只提供一種資料結構,即 table。」以「乾淨的 C」實作,即「C 與 C++ 的交集」,並「在多數平台上開箱即可編譯」。小尺寸:Lua 5.1 的原始碼「約為 17,000 行 C」,其壓縮檔「可以舒適地塞進一張軟碟」,而「建構了所有標準 Lua 函式庫的 Lua 直譯器佔用 143K」。「Adobe Lightroom 超過 40% 是用 Lua 寫成的(這代表約 100,000 行的 Lua 程式碼)。」論及巴西的貿易政策:「從 1977 年直到 1992 年,巴西對電腦硬體與軟體採取強硬貿易壁壘政策(稱為『市場保留』)」,而「那些原因促使 Tecgraf 從零開始實作自己所需的基本工具」;Lua 是「唯一一門誕生於開發中國家、卻達致全球影響力的語言」。前身為 DEL(「資料輸入語言」)與 SOL(「Simple Object Language」)。命名:SOL 在葡萄牙語中是太陽,而「Tecgraf 的一位朋友(Carlos Henrique Levy)建議了『Lua』這個名字(葡萄牙語中的月亮),於是 Lua 就此誕生」。第一版實作於 1993 年 7 月完成,遵循「能跑得起來的最簡單做法」。論及「提供機制,而非政策」:「我們不想把 Lua 變成一門物件導向語言,因為我們不想為 Lua 固定下某一種程式設計典範」;「Lua 不會把任何物件或類別模型強加於程式設計師身上」;「我們決定提供靈活的機制,讓程式設計師能夠構建出最適合應用情境的任何模型」;「可擴充的語意已成為 Lua 的招牌特色」。機制的演化:fallback(Lua 2.1,1995 年)→ tag method(Lua 3.0,1997 年)→ metatable 與 metamethod(Lua 5.0,2003 年);table 索引的 fallback 支援「多種形式的繼承(透過委派)」;「metatable」一詞由 Rici Lake 於 2001 年提出。Lua 作為「一門可擴充的擴充語言」,其 C API 容許「Lua 程式碼與外部程式碼之間的完整溝通」。遊戲:1997 年 1 月,LucasArts《Grim Fandango》的首席程式設計師 Bret Mogilefsky 回報「這款遊戲極其大量的部分都是用 Lua 寫成的」,自此「Lua 在遊戲開發者之間口耳相傳,成為遊戲產業中一項確確實實具有市場價值的技能」。並行:實作搶佔式執行緒需要「並非 ANSI C 一部分」的原語,而「我們當時並不(如今依然不)相信那套標準的多執行緒模型……在一門連 ‘a=a+1’ 都不具確定性的語言裡,沒有人能寫出正確的程式」;透過 coroutine 實現的協作式多工於 Lua 5.0(2003 年)提供。VM:「自 Lua 5.0 起,虛擬機是基於暫存器的」,而「Lua 5.0 的虛擬機是第一套獲得廣泛使用的、基於暫存器的虛擬機」;增量式垃圾回收出現於 Lua 5.1。 

  4. 〈Lua: about〉, Lua.org(官方網站)。「Lua 是一門強大、高效、輕量、可嵌入的腳本語言。」它「以一個小型的 C 函式函式庫實作,以乾淨的 C——標準 C 與 C++ 的共同子集——寫成」,並「在各種 Unix 與 Windows 系統上運行,也運行於行動裝置……嵌入式微處理器……與 IBM 大型主機之上」。將 Lua 描述為結合了「簡單的程序化語法與強大的資料描述構造,後者奠基於關聯陣列與可擴充的語意」,具備動態型別、附帶增量式垃圾回收的自動記憶體管理,並且「快速」又「可攜」。 

  5. 〈Roberto Ierusalimschy〉, Wikipedia,並由其 〈教師簡介〉(PUC-Rio 資訊學系)佐證。1960 年 5 月 21 日生於巴西里約熱內盧;1990 年於 PUC-Rio 取得電腦科學博士學位;PUC-Rio 資訊學正教授;曾於滑鐵盧大學從事博士後研究,並於史丹佛擔任客座教授(2012 年)。Lua 程式語言的創造者與首席架構師、《Programming in Lua》(四版)的作者,以及 LPeg 的開發者——LPeg 是一個用於實作剖析表達式文法的 Lua 函式庫。 

  6. 《Programming in Lua》, Roberto Ierusalimschy 著,Lua.org。這本關於 Lua 的官方書籍,由其首席設計者撰寫,描述了這門語言的設計與使用;第一版可在線上免費取得。它強化了 Lua 圍繞著以下要素的設計:作為唯一資料結構化機制的 table、用於可擴充行為的 metatable、一等函式,以及用於協作式多工的 coroutine。 

  7. Roberto Ierusalimschy、Luiz Henrique de Figueiredo 與 Waldemar Celes,〈The Evolution of Lua〉, HOPL III,2007 年,關於嵌入式使用的註腳。「Crazy Ivan,一具在 2000 年與 2001 年於丹麥贏得 RoboCup 的機器人,其『大腦』是用 Lua 實作的。Lua 直接跑在一顆 Motorola Coldfire 5206e 處理器上,底下沒有任何作業系統(換句話說,Lua 就是那套作業系統)。Lua 儲存在一塊系統 ROM 上,並於啟動時從序列埠載入程式。」這說明了 Lua 觸及裸機嵌入式裝置的能力,那是其小巧、可攜實作的一項衍生結果。 

相關文章

工程哲學:Guido van Rossum,可讀性至上

Guido van Rossum 打造 Python 時押注於一個信念:程式碼被閱讀的次數遠多於被撰寫的次數,因此語言本身就應該為閱讀它的人而優化。

3 分鐘閱讀

工程哲學:Barbara Liskov,契約即型別

Barbara Liskov讓資料抽象成為程式設計的基本要素:型別就是它所信守的契約,而子型別必須兌現其父型別所許下的每一個承諾。

3 分鐘閱讀

The Shader Gallery That Lied: Debugging 216 WebGL Presets

A user said the shader playground looked broken. Pixel-readback testing found 30 dead presets, 11 that never compiled, a…

11 分鐘閱讀