pairs ipairs generics functional-programming lua

generics - ipairs - ¿Hay alguna forma de determinar la firma de una función Lua?



ipairs lua (3)

Estoy bastante seguro de que no puedes hacer eso en Lua.

Recientemente, Lee Baldwin mostró cómo escribir una función de memorización de argumento variable y genérica . Pensé que sería mejor devolver una función más simple donde solo se requiere un parámetro. Aquí está mi intento falso total:

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

Obviamente, select(''#'', ...) falla en este contexto y no haría realmente lo que quiero de todos modos. ¿Hay alguna manera de decir en el interior cómo memozar cuántos argumentos espera?

"No" es una buena respuesta si lo sabes con certeza. No es un gran problema usar dos funciones separadas para memorizar .


Supongo que podría entrar en la información de depuración y determinar esto desde el código fuente, pero básicamente es un "no", lo siento.


Sí, para las funciones Lua pero no para las funciones C. Es un poco tortuoso y un poco superficial.

debug.getlocal funciona en las funciones llamadas, por lo que debe llamar a la función en cuestión. No muestra ninguna pista de ... menos que la llamada pase suficientes parámetros. El siguiente código intenta 20 parámetros.

debug.sethook con el evento "call" da la oportunidad de interceptar la función antes de ejecutar cualquier código.

Este algoritmo funciona con Lua 5.2. Las versiones anteriores serían similares pero no iguales:

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

Un pequeño iterador auxiliar (podría estar alineado para mayor eficiencia):

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

Devuelve la firma (pero podría devolver un conteo de parámetros y usaVarjetas, en su lugar):

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