Lua 函式庫設計工作坊於哈佛舉行,2 月 19 日星期二
內嵌式程式語言 Lua 的設計 [1] 顯示出設計者將近十年來小心思考和關注的成果。然而,隨附 Lua 的標準函式庫並未獲得同等的關注。身為這門語言的使用者,我們有興趣改善函式庫。因此,我們舉辦一場(短暫)的一日工作坊,以提出改善函式庫的建議。向後相容性並非必要條件;如果我們想要,我們可以隨意捨棄所有內容,並重新開始!(不過,我們將遵守目前的語言定義---只有函式庫可以拿來討論。)我們非常有幸能和 Lua 的首席設計者之一 RobertoIerusalimschy 一起工作。我們預計從早上 10 點工作到下午 4 點,中間休息一段時間吃午餐。這是預計作為工作會議,而非演講和座談小組的一天,而且我們希望提出非常具體、明確的建議給 Lua 團隊。因此,招收人數將限制在 20 人左右。
如果您想參加這個工作坊,請告訴我們。請寄電子郵件給 Christian Lindig [lindig@eecs.harvard.edu]。我們希望在 2 月 8 日星期五收到您的消息。
-- ChristianLindig?
請提出您希望在工作坊中討論的內容,即使您無法出席。
ReubenThomas 繼續說:在開始之前,確立標準函式庫的範圍和用途非常重要。在我看來,標準函式庫應該
- 僅提供廣泛需要的功能
- 僅提供無法以 Lua 編寫或在 Lua 中會太低效率的功能
- 僅使用標準 ANSI C 函式庫常式(當然,除了 Lua 自訂程式碼)並且完全可移植
ChristianLinding? 最初列出郵件清單中一些近期的主題,其中大部分可能不適合在工作坊中討論;以下是該清單,並附上說明
- 函式庫的動態載入,以避免為每個應用程式建置 Lua 詮釋器。非 ANSI
- 一個能查詢檔案和目錄屬性的 IO 函式庫。非 ANSI
- 某些形式的協程或非同步執行。非 ANSI;在 4.1 中已大幅處理
- 標準 IP socket 介面。非 ANSI
- UNIX 系統呼叫的介面(例如 exec、kill、waitpid 等)。非 ANSI;poslib 中有此功能,但需要更新至 4.x
- 命名空間管理,讓函式庫能共存。這是關於 Lua 函式庫而非 C 函式庫的重點
- 一個緩衝區函式庫。C 程式碼已存在輔助函式庫中,這的確應該討論。
RiciLake 插話
- 我同意 ReubenThomas 的看法,即標準函式庫應僅提供可以用攜帶式 ANSI C 編寫的服務。不過,顯然 ChristianLindig? 建議的許多增強功能對許多人來說都是有用的,而且也的確被要求過很多次。或許有一個折衷方案:定義共用可用於許多作業系統的一組架構的標準介面,並可能為其中之一提供參考實作。一套經深思熟慮的介面通常是函式庫設計中最困難的部分。
- 這至少可以讓人編寫半攜帶式程式碼,也就是可以移植到已實作標準介面的平台上的程式碼。這種介面的候選對象可能會包含 IP socket、檔案屬性、POSIX 的一小部分和動態連結架構,從 Christian 的清單中挑選一些。
- 極度建議移植標準介面,但也要勸阻過度或不足的實作。精神在於「如果你有這種架構,這就是你把它整合到 Lua 的方式。」然後,只要對實作函式進行簡單的存在測試,就可以知道這個架構是否可用;如果不需要針對作業系統執行測試,這會很好。這雖然有點限制,但並不像純粹的 ANSI C 一樣受限(而且,事實上,符合目前的理念,也就是數學或輸入輸出函式庫可能不適用於特定的嵌入式平台)。
- 我第一次寫這篇文章時忘記的一件事:如果數學函式庫可以在支援它的平台上使用 IEEE-754 運算,那就真的太好了。如果陷阱未受支援,我的心也不會碎,但能夠測試並設定 IEEE-754 規定的例外標記,並至少找到一個方式來關閉陷阱(如果無法以其他方式提供支援),這會很好。當然也要測試 NaN 和 ±Inf。
- 讓我們回到 ReubenThomas…
以下是我更多的高層級想法
1. 是否有可能將更多 Lua 的內部結構作為函式庫公開?
特別是,能夠取得編譯程式的內部結構真的很好,例如能夠將程式碼當作資料來處理(而不是像目前這樣使用字串解譯)。類似地,請參閱我過去在清單上關於能夠插入不同正規表示法引擎或(更有爭議性)垃圾收集器的建議。
2. 用 Lua 重新實作一些標準函式庫怎麼樣?
某些函數,如 assert,可輕易在 Lua 中實作,在 C 中實作幾乎沒有或完全沒有優勢。此外,用 Lua 編寫的函數最適合預先載入至詮釋器中,例如 require (載入至 4.0)。擁有一個架構以將 Lua 函式庫建置到可執行檔中會很容易(bin2c 已完成此工作),而且非常實用。減少用 C 編寫的程式碼量可以提升可用性,並減少維護工作。
3. 還需要做什麼?
就標準函式庫而言,這可以縮減為一個小問題,即是否有任何缺少的 ANSI C 函式庫位元,可對 Lua 有效公開,及一個較大的問題,即是否有任何技術同時可從 C 實作中獲益,又會廣泛使用,如模式比對。我唯一曾經需要新增的(純 ANSI)功能是位元邏輯運算(我的函式庫已廣泛封裝,所以其他人似乎同意)。
最後,如果你接受儘可能少用 C 編寫的論點,顯而易見的下一步就是
4. 用 Lua 編寫的 Lua 標準函式庫該如何處理?
我這裡所提的並不是如 StandardLibraryProposal 中大量豐富的函式庫,只是將一些核心功能建置到 Lua 中。這類可供考慮的候選函數包括 assert 和 require 等,無論在功能性或效能性上,都不一定要在 C 中實作。
一個具體的想法是:如果可以使用 strftime 的完整介面,將會很有用,例如,可以用它來建構目前語言環境的月份或日期名稱清單。能將 nil (NULL) 傳遞至 setlocale 也會很有用。
清單實作 (NickTrout)
使用 Lua 表格實作清單(tinsert()、tremove() 和 getn()
)會涉及將「n
」新增至每個表格,以容納已納入元素的最高索引。這種新增方法有一些問題:-
- 名稱衝突,例如
n
可能為表格中的元素。 - 反覆運算器會反覆運算
n
:-
list = { "a","b","c" }
tinsert(list,"d")
for _,v in list do print(v) end -- will print a,b,c,d,4
foreach(list, function(i,v) print(v) end) -- will print a,b,c,d,4
for i = 1,getn(list) do local v=list[i] print(v) end -- will print a,b,c,d
foreachi(list, function(i,v) print(v) end) -- will print a,b,c,d
- 第一種反覆運算清單的方法清楚便利,但會因為
n
而失敗。最後兩種方法確實可行,但我認為它們沒有那麼簡潔(或有效率?)。
統一的方法表格現已新增,是不是可以捨棄 tinsert、tremove 和 getn
,並新增一個 table()
方法,以建立一個清單表格,其功能類似於 PythonLists 和 PythonDictionaries 的組合。它可能稱為「table」,而非「list」或「dictionary」,因為其功能是兩者的結合,例如。
t = {} -- table with no methods, "clean"
t = table() -- create table with tag/unified methods attached.
t = table{ a=1,b=7,c=8 } -- constructor with dictionary/associative items.
t = table{ a=1 ; "b","c" } -- mixed items.
t = table{ "a","b","c" } -- constructor with list.
t:append("d")
print( t:len() )
t= t:sort( function (a,b) return a>b end )
print( t:count("b") )
t:print() -- print items (rather than "<table>") and/or "print( t:tostring() )"
t:keys():print()
t:values():print()
for _,v in t do print(v) end -- and no "n"!
PeterPrade 對標準函式庫的一些想法
- 我認為命名空間問題應該要加以解決,並提出一個所有人都寫 Lua 函式庫時都應該採用的方法。(像是簡單地加入包裝函數表格 - 例如字串函式庫的「字串」- 「str.find」取代「strfind」- 雖然我不確定自己是否喜歡額外的執行時間成本。如果您不喜歡額外的成本,那麼命名慣例就能做得很好(例如「str_find」)
- 我認為標準函式庫的行為應該要固定,才能撰寫簡單的 Lua 包裝函數(標準 Lua 函式庫函數不應使用給定的參數數量,或將額外的 nil 視為未給定額外參數)另請見 TrailingNilParameters - 這是很重要的,因為許多人都會採用標準函式庫的風格。
- 新增一些用於處理表格的工具(分割 + 結合 (SplitJoin)、複製、對應(使用函數對應表格)、壓縮等)。甚至可以新增一種標準方法,讓表格維持不變(一個非常基本的方法是 PersistentTables),並修正 getn() 問題 (LuaTableSize)!
- 新增一些用於處理檔案的工具(PetersStdLib 的 readfile+writefile - 我發現加入會接受檔案名稱並傳回字串中檔案內容或將字串寫入檔案的函式非常有用,這讓程式碼變得精簡許多)
與其這樣做,我認為直接接受 Lua 的串列當成「原始串列」會更好。這些原始串列由 VM 用於函式引數,而且當然是表格建構函數的結果。實作是公開的(n 欄位)。許多應用程式會更有助於更高層級的串列實作,正如您所建議的。但您肯定希望在您使用的任何類別系統之上實作更高層級的串列。我不認為 Lua 分配應該強加類別系統。所以這種事情應該屬於更大的「Lua 之上」函式庫... --JohnBelmonte
某種基礎表格功能,n
,需要保留,這樣才能針對最基礎的指令碼產生作用for i=1,getn(t) ... end
。無論如何,將 n
加入表格並不熱門,應該將其移除。上述表格功能是作為標準函式庫的選擇性元件或延伸函式庫的部分,這是討論的主題。我瞭解您的觀點,這會有些影響,但由於這非常基礎,所以我真的不認為它會造成多大影響,以至於成為類別系統的基礎。--NickTrout
工作坊摘要
工作坊在一開始由 Roberto Ierusalimschy 就 Lua 進行公開演講。他強調 Lua 的設計理念。這次演講也清楚說明:Lua 的小巧與執行快速,都是經過深思熟慮的實作所帶來的結果。
在演講之後,下列人員出席 Lua 函式庫研習會
- Allyn Dimock <dimock at eecs.harvard.edu>
- Christian Carrillo <carrillo at tenebril.com>
- Christian Lindig <lindig at eecs.harvard.edu>
- John D. Ramsdell <ramsdell at linus.mitre.org>
- John Dias <dias at eecs.harvard.edu>
- Jon Eddy <eddy at eecs.harvard.edu>
- Noam Zeilberger <noam at eecs.harvard.edu>
- Norman Ramsey <nr at eecs.harvard.edu>
- Roberto Ierusalimschy <roberto at inf.puc-rio.br>
- Sukyoung Ryu <syryu at eecs.harvard.edu>
這是不完全的清單,列出在 Lua 函式庫研習會中討論過的主題。或許研討會中其他與會者能幫忙填寫完整。
- 我查看了 Lua 4.0 的 IO 函式庫,並提出了一些變更建議。建議的核心是移除處理檔案的方式隱含函式的功能(如 writeto)。這是因為當您處理多個檔案時,這些功能的通用性不足。討論主要圍繞不這麼激進的方法進行,讓偶爾使用者仍然能將輸入和輸出頻道設為預設值。
- http://www.eecs.harvard.edu/~lindig/papers/lua-iolib/
- http://www.eecs.harvard.edu/~lindig/papers/lua-iolib/slides.pdf
-
- 名稱空間管理是討論中的重要主題。像 IO.open 之類的階層式名稱空間讓每個人可以貢獻函式庫,並簡化函式庫之間的轉換。例如,目前不清楚函式庫應採用物件導向撰寫,還是採用程序導向撰寫。我們可以兩種都用,並擇優採用未來出現的標準。與名稱空間相關的問題包括
- 撰寫模組 X.Y.Z,我該如何參照函式 X.Y.Z.f,而不必知道這是 X.Y.Z?一個本機模組 M 就能解決這個問題。
- 如何將模組對應到檔案系統?Python 的成功建議使用目錄層級。討論的重點在於如何載入函式庫和搜尋路徑。哪些可以用 Lua 撰寫,哪些必須放到核心程式中?
- 在模組中,有沒有辦法「開啟」其他模組,讓其成員可以在不用點號符號的情況下存取?這似乎很難。
- 在執行階段載入物件檔。共識是,這不是技術問題,而是政策問題。該將實作它的微小目標特定模組放到哪裡?John Ramsdell 建議探索 Python 和 GNU Libtool 以取得實作細節。
- 一種機制,用於強制在大型專案中宣告變數。出現了一個彈性的技術解決方案,但我沒有完全理解。Roberto 大概能說明。
- Christian Carrillo 建議對 C API 進行一些變更,以便更好地支援 Lua 的執行緒環境。細節部分我沒有接觸,因為我不撰寫執行緒程式。
-- ChristianLindig?
最新變更 · 喜好設定
編輯 · 歷史記錄
最近編輯時間為 2006 年 7 月 10 日 下午 6:55 GMT (差異)