第一版是為 Lua 5.0 所寫。儘管對後續版本仍有很大的關聯性,但有一些差異。
第四版以 Lua 5.3 為目標,可以在 Amazon 和其他書店取得。
購買這本書,您也可以協助 支援 Lua 專案。
![]() |
程式設計 in Lua | ![]() |
第二部。表格和物件 第 14 章。環境 |
通常,指派就足以取得和設定全域變數。不過,我們常常需要某種形式的元程式設計,例如當我們需要處理一個全域變數時,其名稱儲存在另一個變數中,或在執行時以某種方式計算出來。為了取得這個變數的值,許多程式設計師會忍不住寫出類似下列的程式碼
loadstring("value = " .. varname)()或
value = loadstring("return " .. varname)()例如,如果
varname
是 x
,連接會產生 "return x"
(或 "value = x"
,使用第一個形式),執行時會達成預期的結果。不過,此類程式碼會建立和編譯新的區塊,並產生大量額外的處理工作。您可以使用下列程式碼達成相同的效果,其效率比前一個程式碼高出一個數量級以上
value = _G[varname]由於環境是一個正規的表格,您可以簡單地使用想要的鍵(變數名稱)為其建立索引。
以類似的方式,您可以指派給一個以動態方式計算出來的名稱的全域變數,寫成 _G[varname] = value
。不過要小心:有些程式設計師會對這些函式過於興奮,最後寫出類似 _G["a"] = _G["var1"]
的程式碼,這只不過是寫 a = var1
的複雜方式。
前一個問題的一般化是允許動態名稱中的欄位,例如 "io.read"
或 "a.b.c.d"
。我們使用一個迴圈來解決這個問題,從 _G
開始,並逐個欄位演進
function getfield (f) local v = _G -- start with the table of globals for w in string.gfind(f, "[%w_]+") do v = v[w] end return v end我們仰賴
string
函式庫中的 gfind
來反覆處理 f
中的所有字詞(其中「字詞」是一個或多個字母數字字元和底線的序列)。
設定欄位的對應函式稍微複雜一點。像下列這樣的指派
a.b.c.d.e = v完全等同於
local temp = a.b.c.d temp.e = v換句話說,我們必須擷取到最後一個欄位名稱;我們必須個別處理最後一個欄位。新的
setfield
函式也會在路徑中建立中間的表格,如果它們不存在的話
function setfield (f, v) local t = _G -- start with the table of globals for w, d in string.gfind(f, "([%w_]+)(.?)") do if d == "." then -- not last field? t[w] = t[w] or {} -- create table if absent t = t[w] -- get the table else -- last field t[w] = v -- do the assignment end end end這個新的模式會在變數
w
中擷取欄位名稱,以及在變數 d
中擷取一個可選的後續點。如果欄位名稱後面沒有點,那麼它就是最後一個名稱。(我們將在 第 20 章 中詳細討論模式比對。)
使用先前的函式,呼叫
setfield("t.x.y", 10)會建立一個全域表格
t
、另一個表格 t.x
,並將 10 指定給 t.x.y
print(t.x.y) --> 10 print(getfield("t.x.y")) --> 10
版權所有 © 2003–2004 Roberto Ierusalimschy。保留所有權利。 | ![]() |