Peter Shook

lua-users home
wiki

我是一名 C/Awk/Perl 程序员,对 Perl 的大量晦涩函数和宏(称为 XS)感到很不满意。再加上 Perl 的庞大规模,我转而使用 Lua。虽然 Perl 的扩展工具和文档在我转向 Lua 后有所改进,但我不会再回到 Perl,仅仅因为 Lua 真的用起来很愉快。

Lua 代码示例

C++ 代码示例

C 代码示例

十六进制数字补丁 [1]

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
>

读取目录补丁 [3]

此补丁将 chdiropendirstat 添加到 os 表中。它适用于 Linux、Cygwin 和 Mingwin。

类似 Ruby 的语法糖

对于那些不喜欢一直输入 self.member 的人,这里有一个 [lauxlib.c] 版本,它将 luaL_loadfileluaL_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 程序员,你可能并不关心。

新表和函数补丁 [4]

如果你想神奇地改变本地函数的函数环境呢?这里有一个可疑的补丁,它添加了newfunctionnewtable事件。当在一个环境中创建函数时,如果该环境的元表中存在__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)
现在,即使函数threey变量也是局部的。
$ 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

分离方法补丁 [5]

此补丁更改了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

Coldfire 5282 的 Lua

这是一个使用 m68k-elf-gcc 编译的 tar 文件 [6]

来自补丁 [7]

这是一个从表格值中解包命名值的补丁,这样你就可以做这样的事情

$ 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]


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2020 年 11 月 25 日凌晨 3:15 GMT (差异)