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

Lee Baldwin recently showed how to write a generic variable to memoize arguments . I thought it would be better to return a simpler function where only one parameter is required. Here is my complete 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 will not really do what I want. Is there a way to tell inside memoize how many arguments f expects?


No is a great answer, if you know for sure. You should not use two separate memoize functions.

+5
source share
3 answers

I think you could go into the debugging information and determine this from the source code, but basically it is “no,” sorry.

+4
source

Yes, for Lua functions, but not for C functions. This is a bit painful and a bit sketchy.

debug.getlocal works on called functions, so you need to call this function. It does not display any hints of ... unless the call has enough parameters. The code below tries 20 parameters.

debug.sethook with a call event allows you to intercept a function before running any code.

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

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

Small helper iterator (can be built in to increase 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 a signature (but can return a parameter counter and uses Varargs 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
source

I am sure you cannot do this in Lua.

+2
source

Source: https://habr.com/ru/post/1277239/


All Articles