彼德·舒克 |
|
我是一位 C/Awk/Perl 駭客,不太喜歡 Perl 中大量晦澀難懂的函數和巨集,稱為 XS。這一點以及 Perl 的龐大規模讓我不再使用 Perl 而改用 Lua。雖然自從我改用 Lua 之後,Perl 的擴充工具和文件已有所進步,但我不會再回到 Perl,因為 Lua 真的是一款令人樂於使用的語言。
Lua 可使用 tonumber
函數處理十六進位數字,但我的同事比較習慣使用 C 的 0x 語法,所以,我為他們製作了這個補丁。
此補丁適用於 5.0,但它非常簡單,你可以輕鬆地讓它適用於舊版的 Lua。lua-5.1-alpha 版本 [2]
$ lua Lua 5.0 Copyright (C) 1994-2003 Tecgraf, PUC-Rio > = 0x10 16 > = 0x100 256 > function hex(n) >> return tonumber(n,16) >> end > > = 0xff == hex'FF' true >
此補丁新增 chdir
、opendir
和 stat
至 os
函數表。它適用於 Linux、Cygwin 和 Mingwin。
對於不喜歡一直輸入 self.member
的人來說,以下是 [lauxlib.c] 的一個版本,它將 luaL_loadfile
和 luaL_loadbuffer
改為將 @somename
取代為 self.somename
,並將 @somemethod(...)
取代為 self:somemethod(...)
。
你也可以使用 #
作為註解。
List = setmetatable({}, {__index = table}) List.__index = List function List:new(...) return setmetatable(arg, self) end function List:push(x) @insert(x) return self end function List:pop() return @remove() end function List:shift() return @remove(1) end function List:append(list) for _,elem in ipairs(list) do @insert(elem) end return self end function List:fun(a, b) @a = a @b = b return @n end x = List:new(1, 2, 5) x:foreachi(print) x:push(99) print(x:concat', ') print('fun', x:fun('one', 'two'), x:shift()) x:foreach(print)
$ lua eg.lua 1 1 2 2 3 5 1, 2, 5, 99 fun 4 1 1 2 2 5 3 99 a one b two n 3
對於有 Python 或 PHP 背景的人來說,可能比較希望函數中的變數在預設情況下為局部變數。這很容易在 Lua 5.0 中完成,只要在函數儲存在套件中時,使用 newindex
事件來讓函數擁有新的環境即可。
例如
local Pkg = {} local function fixfuncs(env, name, value) rawset(env, name, value) if type(value)=='function' then print('newfunction', env, name, value) setfenv(value, setmetatable({}, {__index=env})) end end setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newindex=fixfuncs})) y = 0 function one(x) y = x return y end function two() Pkg.y = 99 y = 2 return y end local function three() y = 3 return y end print(y, one(1), y, two(), y, three(), y)
$ lua test1.lua newfunction table: 0xa0459f0 one function: 0xa046ab8 newfunction table: 0xa0459f0 two function: 0xa0466d8 0 1 0 2 99 3 3
Pkg.
或 _G.
前綴。newindex
事件不會對局部函數生效,但是,如果你不是 Perl 程式設計師,你可能不在乎這一點。
如果您想神奇地改變 local 函數的功能環境呢?這裡有一個可疑的修補程式,添加了 newfunction
和 newtable
事件。當在 metatable 中具有 __newfunction
鍵的環境中建立函數時,就會呼叫 newfunction
事件的元方法。
我們可以這樣改寫先前的範例
local Pkg = {} local function fixfuncs(env, f) print('newfunction', env, f) setfenv(f, setmetatable({}, {__index=env})) end setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newfunction=fixfuncs})) y = 0 function one(x) y = x return y end function two() Pkg.y = 99 y = 2 return y end local function three() y = 3 return y end print(y, one(1), y, two(), y, three(), y)
three
的 y
變數也變成了 local。$ lua test2.lua newfunction table: 0xa0459f0 function: 0xa045fb0 newfunction table: 0xa0459f0 function: 0xa046478 newfunction table: 0xa0459f0 function: 0xa040730 0 1 0 2 99 3 99
此修補程式會改變 object:method()
的語義,改用新的單獨 self
事件,而不是一般會使用的 index
事件。這讓您可以在表格中新增一些類別,而且仍然可以保留 index
事件供其他用途使用。
local Pkg = {} local function fixtable(env, t) print('newtable', env, t) setmetatable(t, {__self=table}) end setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newtable=fixtable})) t = { 'one', 'two', 'three' } print(t:concat'/', t:getn(), t:remove(1), t:remove(), t:getn())
$ lua test3.lua newtable table: 0xa0459f0 table: 0xa045f98 one/two/three 3 one three 1
$ src/lua Lua 5.1 (alpha) Copyright (C) 1994-2005 Lua.org, PUC-Rio > write from io > format from string > > function printf(...) write(format(...)) end > > printf("I should have written this patch %d years ago\n", 2) I should have written this patch 2 years ago >
以下是此修正檔的基本版本,其中使用現有的關鍵字 in
而不是 from
[8]