Lua metatable,如何转发未定义的函数?

时间:2015-01-18 23:44:43

标签: lua lua-table metatable

我有一张空桌子,我想充当"网关"到另一个地方的另一组功能。

tbl = {}

我想将此表中的被调用函数作为字符串传递给其他地方:

tbl.someMethod("hello")

我尝试过这个但收效甚微。

hand = {
    __index = function(tbl, name)
      hand[name] = function(...) 
          passToSomewhere(name, ...)
      end
    end,
    __call = function(tbl, name, ...)
        hand[name](...)
    end
}
setmetatable(tbl, hand)
tbl.someFunction("hello!", someTbl, someNumber)

如何通过表格转发未定义的函数而不会抛出错误?

编辑:更多细节

我试图在一次调用中定义并调用表中的函数:

tbl = {}

hand = {
  __index = function(tbl, name)
    print(name)
    tbl[name] = function(...)
      print(...)
    end
  end
}
setmetatable(tbl, hand)

s,e = pcall(tbl.help,"banana","goat")
print(s)

s,e = pcall(tbl.help,"banana","goat")
print(s)

此代码确实有效,但第一个pcall会抛出错误,因为函数尚未定义。

说我想使用一个我知道更新的库,并保持我的脚本兼容,这个库可能不会出现在我的计算机上。我希望通过某个界面将调用转发到此库,但我仍然希望能够以相同的方式调用这些函数。

--For example I would like to call this function like this:
someLib.doSomething(name, age, telephone)

--Instead of passing it through another function:
someOtherLib.invoke("someLib.doSomething", name, age, telephone)

这可能吗?

编辑2:

谢谢@greatwolf!

这是我的工作测试代码。

tbl = {}

hand = {
  __index = function(tbl, name)
    tbl[name] = function(...)
      return print(name, ...)
    end
    return rawget(tbl, name) 
  end
}
setmetatable(tbl, hand)

tbl.help("banana","goat")

1 个答案:

答案 0 :(得分:2)

好的,根据您更新的详细信息,您希望lua翻译此次通话

someLib.doSomething(name, age, telephone)

someOtherLib.invoke("someLib.doSomething", name, age, telephone)
在幕后。你所拥有的几乎就在那里,你只需要返回新创建的函数:

__index = function(tbl, name)
  tbl[name] = function(...)
    return someOtherLib.invoke("someLib."..name, ...)
  end
  -- return tbl[name] works too, I used rawget to indicate 
  -- no further __index lookup should be done
  return rawget(tbl, name) 
end

现在,如果您的someOtherLib只是一个功能表,那么我的建议也会起作用

setmetatable(tbl, {__index = someOtherLib})

现在如果你的someOtherLib提供了一些你想要调用的函数而没有实际调用它,__index可以在不创建额外的封装包装的情况下中继它

__index = function(tbl, name)
  tbl[name] = someOtherLib.getFuncByName(name)
  return tbl[name]
end

此处不需要__call元方法。