Peter Shook |
|
我是一名 C/Awk/Perl 程序员,当初对 Perl 庞大且晦涩的 XS 函数和宏列表感到非常不满。加上 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 >
此补丁在 os 表中添加了 chdir、opendir 和 stat。它适用于 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 程序员,您可能并不在乎。
如果您想神奇地修改局部函数的函数环境怎么办?这里有一个不那么正统的补丁,它添加了 newfunction 和 newtable 事件。每当在具有 __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 变量也是局部的。$ 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() 的语义更改为使用一个新的、独立于 index 事件的 self 事件。这允许您为表添加一些类功能,并将 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]