Is there a way to determine the signature of a Lua function?

妖精的绣舞 提交于 2019-12-18 08:26:08

问题


Recently, Lee Baldwin showed how to write a generic, variable argument memoize function. I thought it would be better to return a simpler function where only one parameter is required. Here is my total bogus attempt:

local function memoize(f)
   local cache = {}

   if select('#', ...) == 1 then
      return function (x)
                if cache[x] then
                   return cache[x]
                else
                   local y = f(x)
                   cache[x] = y
                   return y
                end
              end
   else
      return function (...)
                local al = varg_tostring(...)
                if cache[al] then
                   return cache[al]
                else
                   local y = f(...)
                   cache[al] = y
                   return y
                end
             end
   end
end

Obviously, select('#', ...) fails in this context and wouldn't really do what I want anyway. Is there any way to tell inside memoize how many arguments f expects?


"No" is a fine answer if you know for sure. It's not a big deal to use two separate memoize functions.


回答1:


I guess you could go into the debug info and determine this from the source-code, but basically it's a "no", sorry.




回答2:


Yes, for Lua functions but not C functions. It's a bit torturous and a little sketchy.

debug.getlocal works on called functions so you have to call the function in question. It doesn't show any hint of ... unless the call passes enough parameters. The code below tries 20 parameters.

debug.sethook with the "call" event gives an opportunity to intercept the function before it runs any code.

This algorithm works with Lua 5.2. Older versions would be similar but not the same:

assert(_VERSION=="Lua 5.2", "Must be compatible with Lua 5.2")

A little helper iterator (could be inlined for efficiency):

local function getlocals(l)
  local i = 0
  local direction = 1
  return function ()
    i = i + direction
    local k,v = debug.getlocal(l,i)
    if (direction == 1 and (k == nil or k.sub(k,1,1) == '(')) then 
      i = -1 
      direction = -1 
      k,v = debug.getlocal(l,i) 
    end
    return k,v
  end
end

Returns the signature (but could return a parameter count and usesVarargs, instead):

local function dumpsig(f)
  assert(type(f) == 'function', 
    "bad argument #1 to 'dumpsig' (function expected)")
  local p = {}
  pcall (function() 
    local oldhook
    local hook = function(event, line)
      for k,v in getlocals(3) do 
        if k == "(*vararg)" then 
          table.insert(p,"...") 
          break
        end 
        table.insert(p,k) end
      debug.sethook(oldhook)
      error('aborting the call')
    end
    oldhook = debug.sethook(hook, "c")
    -- To test for vararg must pass a least one vararg parameter
    f(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
  end)
  return "function("..table.concat(p,",")..")"  
end



回答3:


I'm pretty sure you can't do that in Lua.



来源:https://stackoverflow.com/questions/142417/is-there-a-way-to-determine-the-signature-of-a-lua-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!