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