请注意,这个问题与纯Lua有关。我无权访问任何模块或C端。另外,我不能使用IO,OS或调试库。
我想要做的是一个接收的函数,作为参数:
'可调用值',我的意思是可以调用的值。这可以是:
__call
metamethod)以下是可调用表的示例:
local t = {}
setmetatable(t, {
__call = function() print("Hi.") end
})
print(type(t)) --> table
t() --> Hi.
这是功能:
function delay(seconds, func)
-- The second parameter is called 'func', but it can be anything that is callable.
coroutine.wrap(function()
wait(seconds) -- This function is defined elsewhere. It waits the ammount of time, in seconds, that it is told to.
func() -- Calls the function/table.
end)()
end
但我有一个问题。如果参数'func'不可调用,我希望函数抛出错误。
我可以检查它是否是一个功能。但是如果它是一个带有metatable的表允许调用呢?
如果表的metatable不受__metatable
字段的保护,那么,我可以检查metatable以确定它是否可调用,但是,否则,我该怎么做?
请注意,我还考虑过尝试使用pcall
调用'func'参数来检查它是否可调用,但为了做到这一点,我需要提前调用它。
基本上,问题在于:我需要知道函数/表是否可调用,但不试图调用它。
答案 0 :(得分:4)
一般来说,如果metatable不希望你能够得到它(通过将__metatable
定义为特殊的东西),那么你就不会得到它。不是来自Lua。
但是,如果你想作弊,你可以随时使用debug.getmetatable
,这将返回与该对象相关联的元表。
您不必过早地使用pcall
调用任何内容。观察:
pcall(function(...) return PossibleFunction(...) end, <insert arguments here>)
答案 1 :(得分:0)
这种改进Nicol的答案的尝试仍然存在需要调用表的问题,但它告诉所提供的表是否实际上是可调用的。即使表是可调用的,如果在执行false
元方法期间出现错误,__call()
也将返回local result = {pcall(PossibleFunction, ...)}
if not result[1] then
if result[2]:match"^attempt to call" then
error("The provided value is not callable.")
else
-- Table was callable but failed. Just hand on the error.
error(result[2])
end
end
-- Do something with the results:
for i = 2, #result do
print(result[i])
end
。
JNI- java.lang.UnsatisfiedLinkError: Native error: method not found
以这种方式检查错误消息然而感觉不是很“干净”(如果使用的Lua解释器例如用本地化的错误消息修改了怎么办?)。
答案 2 :(得分:-1)
function iscallable(x)
if type(x) == 'function' then
return true
elseif type(x) == 'table' then
-- It would be elegant and quick to say
-- `return iscallable(debug.getmetatable(x))`
-- but that is actually not quite correct
-- (at least in my experiments), since it appears
-- that the `__call` metamethod must be a *function* value
-- (and not some table that has been made callable)
local mt = debug.getmetatable(x)
return type(mt) == "table" and type(mt.__call) == "function"
else
return false
end
end
return iscallable
那你就可以做
> = iscallable(function() end)
true
> = iscallable({})
false
> = iscallable()
false
> = iscallable(nil)
false
> x = {}
> setmetatable(x, {__call=function() end})
> = iscallable(x)
true
如果您无权访问调试库,那么您可能会很难完全准确,因为您可能会弄乱元表。您可以使用pcall
,但很难正确区分出错误。即使您按照此处的其他答案搜索特定的错误字符串,也可能是因为该函数内部的某些内容被称为不可调用,如果可以的话,该特定值也无法被调用。