Lua中语法糖(冒号)的奇怪行为

function string.test(s)
    print('test')
end

a = 'bar'
string.test(a)
a:test()

一切正常,直到下一个示例。

function table.test(s)
    print('test')
end

b = {1,2,3}
table.test(b)
b:test() -- error

为什么我得到了错误?

在字符串上工作得很好。

点赞
用户282536
用户282536

默认情况下,表没有像字符串那样的元表。

尝试使用:

function table.test(s)
    print('test')
end

b = setmetatable({1,2,3}, {__index=table})
table.test(b)
b:test() -- 错误
2015-11-30 00:14:09
用户3979429
用户3979429

虽然 daurn 很好地回答了你的问题,但让我解释一下为什么会这样。

在 Lua 中,所有的数据类型都可以有元表(metatable)。(虽然当处理数字、布尔等时会有所不同,请参见 debug.setmetatable。)这也包括字符串。默认情况下,元表被设置为使用 __index 索引字符串库,这使得像 print(s:sub(1,5))(其中 s 是一个字符串)这样的语法糖成为可能。

但是,表(table)并非如此。默认情况下,表没有元表。你必须使用 setmetatable 手动设置它。

总之,享受一下这段代码片段

debug.setmetatable(0,{__index=math})
debug.setmetatable(function()end,{__index=coroutine})
debug.setmetatable(coroutine.create(function()end), {__index=coroutine})
local function Tab(tab)
    return setmetatable(tab,{__index=table})
end

这基本上允许你在数字上使用数学函数

local x = 5.7
print(x:floor())

并且使用协程函数实现类似的功能:

print:create():resume()

如果你问我,这样做挺 hacky 的。

当然,你还可以创建表并在它们上使用表函数:

local x = Tab{1,2,3,4}
x:insert(5)
x:remove(1)
print(x:concat(", "))

我觉得很难想象还有人不喜欢这样的酷技巧。

2015-11-30 03:27:17