Lua Five Two

lua-users home
wiki

Lua 5.2 是 Lua 自 5.1 之後最新的重大版本修訂[1]。此頁面有一些關於 alpha/beta 測試期間郵件清單的資訊,但這些資訊可能已過時或不正確。Lua 5.2 的官方資訊和下載內容可在 [www.lua.org/manual/5.2] 取得。

範圍

雖然 5.1.x 版本嚴格來說只是 5.1 的錯誤修正版本[12][13][2],但 Lua 5.2 允許進行破壞完全相容性設計變更。

歷程

背景資訊

盡情更新參考資料!(也可以更新這裡的任何其他內容。)-- AlexanderGladysh

TODO:下列某些段落可能需要更新,以反映最終的 Lua 5.2.0 版本。

緊急垃圾收集

當配置失敗時,Lua 核心會強制執行 GC。

參考資料

世代垃圾收集(選擇性且實驗性質)

短暫表

僅包含弱鍵的表只會在可以存取鍵時檢視值。

參考資料

具有完成處理程序的使用者資料

具有完成處理程序的使用者資料會保留在 GC 的分隔清單中

參考資料

非字串錯誤訊息

Lua 詮譯器能更好地處理非字串錯誤訊息。

參考資料

xpcall() 已改進

xpcall() 現在可接受呼叫函式傳遞的引數,就像 pcall() 一樣

參考資料

package.searchpath()

新增函式 package.searchpath() 可搜尋您的檔案,就像 require() 所做的一樣。

參考資料

package.config

編譯時模組系統設定值目前在 package.config 中提供,並已記錄下來。

參考資料

__pairs 和 __ipairs

現在可以使用新的 __pairs 和 __ipairs 元方法來過載迴圈疊代。

參考資料: GeneralizedPairsAndIpairs

__len

目前除了字串之外的所有類型都會尊重 __len 元方法。先前 __len 並未受到資料表的尊重。

參考資料

%q 已改進

string.format("%q") 現在會轉義控制字元。

參考資料

Goto 語法 (包括模擬 continue 及標記的 break 語法)

參考資料

字串字面中的十六進位表示法

除了舊有的 \255 表示法,您現在可以在字串中書寫 \xFF。

參考資料

數值字面中的十六進位小數和指數

您現在可以輸入 0x0.A 或 0xA23p-4 形式的數值常數。在後者的情況中,'p' 表示以十進位表示的二進位指數 (手冊未清楚說明:我假設指數與其他部分一樣,都是十六進位的)。此功能可能在手寫的程式碼中沒有什麼用,但它允許精確地反序列化使用 string.format 的十六進位選項所序列化的數字。

但是,儘管包含了一個官方的位元操作函式庫,但二進位字面仍在不受支援。

參考資料

更安全的 os.date()

os.date() 現在只允許 ANSI C 選項。

參考資料

luaL_testudata()

新的 luaL_testudata API 函式,類似於 luaL_checkudata,但會向呼叫端發出無效使用者資料信號,而不是擲回錯誤。

參考資料

常數合併簡化

如果第二個引數是零,則不再合併除法和模數運算。

參考資料

更自由地使用 yield()

現在可以使用 yield() 穿越 metamethods、for 迴圈反覆器 pcall 和 xpcall 呼叫,以及現在未記錄的 table.foreach[i] 呼叫。

此外,C API 呼叫是用於實作自己的與 yield 相容的 C 函式。

位元運算模組

現在可以在 Lua 中處理位元,不需要第三方模組或修補程式。不過,不會使用任何現有的實作。

參考資料

luaL_tolstring()

luaL_tolstring 已記錄。您可透過 tostring() 規則正式將 Lua 值轉換成 C。

參考: [20]

新函式:lua_tonumberx 和 luatointegerx

參考資料

詞彙環境

_ENV

參考資料

已棄用的 getfenv() / setfenv()

getfenv() 和 setfenv() 已棄用,取而代之的是新的詞彙環境。偵錯庫中的對應函式依然存在。

參考資料

函式/封閉建構最佳化

為重複使用快取匿名函式/封閉。現在在移除 getfenv/setfenv 的情況下,可以進行最佳化。TODO:新増更詳盡的描述和範例。

loadin()

新的 loadin(env,chunk) 函式可在特定環境載入區塊。請注意,區塊引數也可以是字串。

fn,err = loadin({x=1,y=2},"return x+y")

參考資料

load() 區塊類型篩選器

可以禁止 load() 載入位元組碼和/或原始程式區塊。載入時已移除位元組碼驗證。

參考資料

Lua 執行緒環境

Lua 執行緒 (別名常式函式) 不再有各自的環境。

參考:(有人嗎?)

ABI 和位元組碼的不相容性

如同預期,Lua 5.2 ABI 和位元組碼與 5.1 不相容。

參考資料

已從 5.1 棄用的功能

已移除從 5.1 棄用的大部分功能。預設關閉新的已棄用功能。

參考:(有人嗎?)

偵錯模塊不再預設載入

如果您需要,請 require()。

假設這是指偵錯函式庫,看起來發行版中並非如此 - 偵錯函式庫在 luaL_openlibs 載入的清單中。--JohnHind

參考資料

協程函式庫提升為一個完全成熟的函式庫

先前協程函式庫是基本函式庫載入器函式載入的子函式庫。在 5.2 中,它獲得了自己的載入器函式並提升為一個正常的函式庫。它包含在 luaL_openlibs 載入的清單中,因此唯有在您的執行階段不使用 luaL_openlibs 時,此變更才顯得重要。

手冊中有一個小錯誤:此變更反映在第 6 節中,但第 6.2 節仍提及協程函式庫是「基本函式庫的子函式庫」。

參考資料

debug.getlocal 參數名稱

debug.getlocal 取得非活動函式的參數名稱。在 debug.getlocal ([thread,] f, local) 中,「參數 f 也可以是一個函式。在這種情況下,getlocal 僅傳回函式參數的名稱。」

參考資料

Upvalue 處理

新的函式可偵測兩個 upvalue 是否相同,並在它們不同時將它們合併。

參考資料

額外偵錯資訊

debug.getinfo() 和 lua_getinfo() 現在傳回呼叫堆疊中函式的額外資訊

參考:(有人嗎?)

範本:%f 已記錄

前緣範本現在已記錄。

參考資料

範本:%g

新範本 %g 代表所有可列印字元,空白除外。

string.gsub repl

string.gsub [6] 現在如果取代字串包含一個「%」,並接著一個字元,而不是允許的「%」或數字,就會引發錯誤。

ipairs 行為變更 (此功能已撤消)

現在 ipairs() 根據表格中的 #t 元素進行反覆運算。在 5.1 中,它進行反覆運算時會一直到第一個 nil。

參考: 原始碼:lua-5.2.0-work4/src/lbaselib.c 第 213 行

select() 負數

您可以傳遞負面索引給 select(),以從變數參數的結尾取得參數 (以順序方式)。

參考資料

math.log10() 和 math.log()

math.log10() 已不建議使用。將 10 用作 math.log() 的第二個參數。

參考:(有人嗎?)

移除 table.maxn()

table.maxn 已不建議使用。

參考資料

table.unpack() 和 table.pack()

unpack() 已更名為 table.unpack()。已新增 table.pack(),將引數封裝到一個 table 中,並將引數數目儲存到 table 的「n」欄位中。

參考資料

增強的 pipe 支援

如果檔案是由 io.popen() 開啟的,則 file:close() 會傳回程式的結束代碼。

參考資料

更好的停止 GC 處理

呼叫 collectgarbage("step") 不再會在 GC 停止時重新啟動 GC。另外,您可以透過呼叫 collectgarbage("isrunning") 了解 GC 是否已停止。當然,您也可以在 C API 中執行相同的操作。

參考:(有人嗎?)

識別碼的區域設定

Lua 識別碼不再可以使用依區域設定而定的字元。

參考資料

新的 Registry 欄位

以下是 5.2.0 版本中 Lua 使用 registry table (在偽索引值 LUA_REGISTRYINDEX 中) 的完整清單。

由 lua_newstate 安裝

由「package」函式庫載入器安裝

由「IO」函式庫載入器安裝

手冊說明:「與全域變數名稱一樣,字串鍵以底線開頭後面是大寫字母時,會留作 Lua 使用。」但請注意,與「FILE*」鍵一樣,Lua 並不嚴格遵循此規則。

字串的元資料表並未在 registry 中參考,但它僅將字串函式庫 table 本身建索引,因此新增至該元資料表中的函式會自動作為字串物件的函式。

參考資料

輕量級 C 的函式 / lua_cpcall 的改進

lua_pushcfunction 無須再配置。此舉更有效率且不會因錯誤而引發。同時也無需 lua_cpcall(),此函式已從 API 中移除。此外,不再需要可支援多重引數與傳回值的 lua_cpcall 版本,因為 lua_pcall 現已能這麼做。

移除 LUA_GLOBALSINDEX

如有需要,請使用註冊表的 LUA_RIDX_GLOBALS (或在未變更 C 函式環境時,使用 LUA_ENVIRONINDEX)。

參考:(有人嗎?)

lua_getglobal()、lua_setglobal() 和 lua_register()

這些函式適用於 C 函式環境,而非狀態的全球環境,以更準確地反映 Lua 使用全域變數的方式。

參考:(有人嗎?)

luaL_typerror() 已不建議使用

參考資料

lua_compare()

新增函式 lua_compare() 取代已不建議使用的 lua_equal() 與 lua_lessthan()。

參考資料

lua_arith()

新增函式 lua_arith() 以 Lua 的方式進行 Lua 值的運算。

參考資料

物件長度(C)

lua_objlen() 已重新命名為 lua_rawlen()。lua_len() 則已新增用於支援 __len 元方法。

參考資料

更新 lua_checkstack()

lua_checkstack 現僅傳回錯誤碼(絕不引發錯誤)。如果您想引發錯誤(附帶錯誤字串),請使用 luaL_checkstack。

參考資料

lua_pushstring() 和 lua_pushlstring() 增強功能

現在,它們回傳指標到內部字串表示。

參考:(有人嗎?)

lua_copy()

允許在堆疊上複製 Lua 值(取代目標槽位的現有值)。

參考資料

Lua 執行階段版本檢查

新增兩個函式,lua_version() 和 luaL_checkversion(),供使用者檢查執行階段版本和地址空間正確性。這有助於在多個 Lua 實例連結到可執行檔時,防止令人害怕的難懂錯誤。luaL_checkversion() 從 luaL_register() 呼叫,所以當需要大部分模組時,這些檢查會自動執行。

參考資料

luaL_traceback()

新函式,可產生堆疊追蹤,就像 debug.traceback() 一樣。

參考資料

LUA_ERRGCMM 和 LUA_OK

LUA_ERRGCMM 是新的執行階段錯誤碼,用於表示 __gc 中繼資料方法的錯誤。新增 LUA_OK 以維持對稱,表示所有事情都合乎預期,且沒有錯誤。

參考資料

*nix 上更好的動態函式庫載入

現在,Lua C 模組可以使用全域符號載入動態函式庫(感謝 RTLD_GLOBAL)。

參考:(有人嗎?)

Windows 上的動態函式庫載入改良

Windows 上的 DLL 搜尋路徑處理已改良。

每一段落更多常數

每一段落最大常數數目從 2^18 增加到 2^26。有了這個,就可以輕鬆轉儲龐大表格!

參考資料

剖析器最佳化

剖析器不再使用自動陣列,因此所消耗的 C 堆疊空間較少。

參考資料

新的浮點數雜湊函式

浮點數的新雜湊函式,在 lua_Number 定義為 long double 於某些 64 位平台時,能更好的處理這些情況。

參考資料

改善 file:write()

file:write() 會傳回檔案內容,以便進行串連呼叫。

參考資料

新檔案中的結尾字元保留:read 結尾檔案:lines

檔案:read 中新的 "*L" 選項如同 "*l",但會保留結尾字元 (若有)。另外,file:lines 中的新參數 `keepNL` 會保留換行符號。

os.exit() 進行改善

它可以選擇在 Lua 狀態下呼叫 lua_close()。

參考資料

os.execute() 介面變更

"函式 os.execute 目前在命令成功終止時傳回 true,否則傳回 nil 和錯誤資訊。" [10]

範例

$ lua51 -e "os.exit(3)"; echo $?
3
$ lua51 -e 'print(os.execute[[lua -e "os.exit(3)"]])'
768
$ lua52  -e 'print(os.execute[[lua -e "os.exit(3)"]])'
nil	exit	3
$ perl -e 'print(system(qq(perl -e "exit(3)")),"\n")'
768
$ python -c "import os; print(os.system(\"python -c 'import os; os._exit(3)'\"))"
768

呼叫資訊堆疊目前是連結清單

??

參考資料

解決模組系統和模組功能問題

module/luaL_register 函式已被棄用,並由 luaL_newlib 及 luaL_setfuncs 取而代之。另外,還有一個新函式 luaL_requiref

我相信這是一個比手冊或其他文件建議的更重大變更。從表面上看,在過去你可以寫下例如 require 'coroutine',但現在你必須寫下 coroutine = require 'coroutine'。這絕對是有用的改善,但如果我理解正確,這將破壞許多現有的程式碼。手冊的「變更」區段並未明確說明這一點。更糟的是,require 的文件未清楚說明回傳值的目的。你必須從字裡行間看出,意圖是回傳模組的整體表格或值「true」(如果模組未匯出整體表格,則會傳遞這個意圖,這取決於遵循一些規則的模組載入器,但這些規則並未明確說明)。

手冊中提到「載入器找到後,require 會呼叫載入器,並傳入兩個參數:模組名稱和一個額外的值,依據載入器取得方式不同而定。[...] 如果載入器傳回任何非零值,require 會將傳回的值指派給 package.loaded[modname]。如果載入器沒有傳回非零值,且沒有將任何值指派給 package.loaded[modname],require 則會將 true 指派給此項目。無論如何,require 會傳回 package.loaded[modname] 的最終值。」這不清晰嗎?不過我可能要補充一點,就是允許將 true(而非模組表格)指派給 package.loaded[modname] 通常是應該避免的,而是一種備援行為,在沒有任何較佳可用值的情況下,至少確保模組載入器不會因多個 require 呼叫而執行多次。現在,關於載入器應傳回什麼,它通常應該是一個表格 [21],但官方 Lua 參考手冊可能會因為 MechanismNotPolicy 設計原則而對此保持沉默。有時模組載入器會傳回函數(通常為物件建構函式),儘管傳回 FuncTables(也就是具有呼叫運算式的表格)可能較佳,因為 require'foo'._VERSION 代表模組版本是近乎標準的(ModuleVersioning),這在 FuncTables 中仍然是可行的。順道一提,module 函數雖然在 5.2 中已發生不建議使用,但在關閉不建議使用的功能之前仍然可用,而且呼叫 module 會設定 package.loaded[modname](以及全域)。--DavidManura

luaL_requiref(C API)與 require(Lua)做比較:後者只要模組名稱,前者則需要模組名稱、函式庫載入器函數和一個設定為 'true' 的標記,以將載入器函數的傳回值儲存在與函式庫同名的全域中。luaL_openlibs 使用標記設定為此設定的 luaL_requiref。因此,它會開啟標準函式庫,且其全域表格初始化後的行為如預期般。不過,使用 require 從 Lua 開啟的函式庫必須使用傳回值明確設定全域。

如果上述兩個段落有誤解,請隨時更正!

我認為 luaL_requiref 只是一個特定案例(例如 linit.c)的便利函數。例如,它假設載入器是 C 函數 (lua_CFunction),且目的地表格是 LUA_RIDX_GLOBALS,所以它並非完全一般化。「必須明確設定全域」並非完全正確,因為通常偏好明確地設定區域,local foo = require 'foo',而不會破壞 _G。--DavidManura

抱歉,DavidManura,我並非真正想開啟一場關於政策的討論/批判,只是想警告別人我剛發現的一個實務問題,而且是親身體驗得來的。我的執行階段預設不載入大部分的標準函式庫,而直接將其載入函式放入 preloads 表中(我是這麼做以節省 RAM)。在從 5.1.4 轉換到 5.2 之後,我發現,例如使用 require 'coroutine' 的 Lua 已經無法運作,我必須將其改寫成 coroutine = require 'coroutine'。這讓我想到,如果第三方函式庫開發人員跟隨標準函式庫訂定的示範(我並不想說是政策),他們也有可能破壞既有的 Lua 程式碼。大部分使用者不會注意標準函式庫的這項變更,因為執行階段通常呼叫 luaL_openlibs 來載入它們,然後 luaL_openlibs 再去呼叫 luaL_requiref。-- JohnHind

參考資料

版本專用的環境變數

新增環境變數 LUA_PATH_5_2 等


我們在 5.2 中拿不到什麼

...還是我們想得到它?

歡迎你在這裡放上你心儀的功能,假設它有其他人支援,而且遭到 Lua 作者拒絕在 5.2 中納入。請保持禮貌。--AlexanderGladysh

string.pack/string.unpack

struct/lpack 的相關功能

參考資料

拒絕動機:(有連結嗎?)

Token 篩選器

或其他「meta」工具

參考資料

拒絕動機:(有連結嗎?)

#line 指示詞

這將與 C 預處理指令中的 #line 指示詞類似 [11]。主要目的是允許預處理器在產生 Lua 程式碼時將它輸出,讓除錯時的行數與檔案名稱和預處理之前的原始程式碼相符。

移除自動強制轉型

lua_rawtostring / rawtostring

從數字取得不經強制轉型的字串。

參考資料

拒絕動機:(有連結嗎?)

模組名稱中的連字號

模組版本號碼目前預期放在名稱的左側,這相當不尋常。

參考資料

拒絕動機:(有連結嗎?)

改善確定性資源清除

使用類似 package.clean 的內容替換 package.seeall

使用類似 ModuleDefinitionpackage.clean 解決方案的內容替換 package.seeall,但更新為支援 _ENV。package.seeall 並未區分公開的模組表和私密的實作環境。

參考資料

建議

使用者為 5.2 建議的部分功能/變更列於 FeatureProposals。要求應張貼至郵件清單。

另請參閱


最近變更 · 偏好設定
編輯 · 歷史
最後編輯於 2012 年 5 月 20 日 上午 3:00 GMT (diff)