Lua函数语法糖:数字开头的名称

例如:

bar = {}
bar.name = 'test'
bar['123.com'] = function(self) print(self.name) end

我不能像下面这样调用方法:

bar:['123.com']()
stdin:1: '<name>' expected near '['

即使下面这个可以工作:

bar['123.com'](bar)

但这样有点丑。这种情况是否有语法糖?

或者如果确实不能做到,Lua团队会在将来添加这个语法吗?

或者他们有意这样做?

原文链接 https://stackoverflow.com/questions/10202658

点赞
stackoverflow用户1302958
stackoverflow用户1302958

不,我们不能按照你想要的方法来调用。你应该只按照以下语法来调用方法。

bar['123.com'](bar)
2012-04-18 04:17:50
stackoverflow用户185316
stackoverflow用户185316

你可以使用 闭包

bar = {}
bar.name = 'test'
bar['123.com'] = function() print(bar.name) end
bar['123.com']()

function bar:addBar(name)
    bar[name] = function() print(self.name) end
end

bar:addBar('456.com')

bar['456.com']()
2012-04-18 04:21:27
stackoverflow用户837856
stackoverflow用户837856

不要这样做 - 永远不要。

bar = {
    ['123.com'] = function(self)
        print("YAY!", self)
    end
}
function f()
    print(bar)
    bar:WHATTHE()
end

function crazy(f, patt, repl)
    local f_str = string.dump(f)
    local newf_str = string.gsub(f_str, "WHATTHE", "123.com")
    assert(#newf_str == #f_str, "replacement must be of same length")
    local newf = loadstring(newf_str)
    setfenv(newf, getfenv(f))
    return newf
end

f = crazy(f, "WHATTHE", "123.com")

f()
--[[ Output:
    table: 005EB688
    YAY!    table: 005EB688
]]
2012-04-18 09:50:24
stackoverflow用户284969
stackoverflow用户284969

没人知道 Lua 的维护者将在未来的版本中添加什么(他们非常守口如瓶),但我猜想他们不太可能没有至少被要求就添加它,我从来没有看到过 Lua 邮件列表中有关此类功能的要求...

虽然我可以感觉到,这种功能似乎很奇怪:人们真的有多频繁地想要调用具有类似“奇怪”名称的方法吗?鉴于这一点,而且这个“变通方法”实际上并不差,不清楚是否值得增加实现复杂性来支持这样的功能(除非它非常简单)。

如果您要尝试询问,请在 Lua 邮件列表中发布相关信息,这里是大多数讨论的地方:lua-l@lists.lua.org

2012-04-18 23:59:32
stackoverflow用户312586
stackoverflow用户312586

只需创建一个不以数字开头的别名并使用它。

bar.name123 = bar['123name']

bar:name123()
2012-04-19 08:13:02
stackoverflow用户98528
stackoverflow用户98528

你可能想考虑像下面这样的解决方案(可以在http://www.lua.org/cgi-bin/demo上在线测试):

bar = {}
bar.name = 'test'
bar['123.com'] = function(self) print(self.name) end

bar2 = setmetatable({}, {
  __index = function(t, key)
    return function(...)
      return bar[key](bar, ...)
    end
  end
})

bar2['123.com']()
-- output: test

你也可以改变bar本身的行为,只要在分配任何值之前这样做-例如:

bar = {}

local privatekey = {}
setmetatable(bar, {
  __index = function(t, key)
    local value = rawget(t, privatekey)[key]
    if type(value) ~= 'function' then
      return value
    end
    return function(...)
      return value(t, ...)
    end
  end,
  __newindex = function(t, key, value)
    rawset(t, privatekey, rawget(t, privatekey) or {})
    rawget(t, privatekey)[key] = value
  end
})

bar.name = 'test'
bar['123.com'] = function(self) print(self.name) end
bar['123.com']()
-- output: test
2012-04-19 14:30:09