2011-10-25 28 views
5

Lo siento si esto es demasiado obvio, pero soy totalmente nuevo en lua, y no puedo encontrarlo en la referencia.En Lua, ¿hay alguna función que, dada una función, devuelva su nombre como una cadena?

¿Hay una función NAME_OF_FUNCTION en Lua, que dada una función me da su nombre para que pueda indexar una tabla con ella? Razón por la que quiero que esto es lo que quiero hacer algo como esto:

local M = {} 

local function export(...) 
    for x in ... 
    M[NAME_OF_FUNCTION(x)] = x 
    end 
end 

local function fun1(...) 
... 
end 

local function fun2(...) 
... 
end 

. 
. 
. 

export(fun1, fun2, ...) 

return M 
+0

Podría pasar el hilo para exportarme, pero pensé en preguntar porque creo que es más elegante pasar el mismo func. Aunque es muy difícil de tener, ya que el nombre tal como está en la fuente solo vive en la fuente. – Paralife

+1

Creo que se equivoca en este punto 'el nombre tal como está en la fuente vive solo en la fuente'. Eso es cierto para la mayoría de los lenguajes estáticos y compilados, pero los lenguajes dinámicos/de scripts envían las funciones buscando sus nombres, por lo que pueden tener un enlace tardío (y permitir volver a vincular funciones al código de parche mono, etc.) – fortran

+1

posible duplicado de [ Nombre del objeto Stringify en Lua] (http://stackoverflow.com/questions/6800648/stringify-object-name-in-lua) – finnw

Respuesta

5

Simplemente no existe tal función. Supongo que no existe tal función, ya que las funciones son ciudadanos de primera clase. Entonces, una función es solo un valor como cualquier otro, al que se hace referencia por variable. Por lo tanto, la función NAME_OF_FUNCTION no sería muy útil, ya que la misma función puede tener muchas variables apuntando a ella, o ninguna.

Puede emular uno para funciones globales, o funciones en una tabla al recorrer la tabla (arbitraria o _G), verificando si el valor es igual a x. Si es así, has encontrado el nombre de la función.

a=function() print"fun a" end 
b=function() print"fun b" end 
t={ 
    a=a, 
    c=b 
} 
function NameOfFunctionIn(fun,t) --returns the name of a function pointed to by fun in table t 
    for k,v in pairs(t) do 
     if v==fun then return k end 
    end 
end 
print(NameOfFunctionIn(a,t)) -- prints a, in t 
print(NameOfFunctionIn(b,t)) -- prints c 
print(NameOfFunctionIn(b,_G)) -- prints b, because b in the global table is b. Kind of a NOOP here really. 

Otro enfoque sería para envolver funciones en una mesa, y tienen un metatabla estableció que llama a la función, así:

fun1={ 
    fun=function(self,...) 
     print("Hello from "..self.name) 
     print("Arguments received:") 
     for k,v in pairs{...} do print(k,v) end 
    end, 
    name="fun1" 
} 
fun_mt={ 
    __call=function(t,...) 
     t.fun(t,...) 
    end, 
    __tostring=function(t) 
     return t.name 
    end 
} 
setmetatable(fun1,fun_mt) 
fun1('foo') 
print(fun1) -- or print(tostring(fun1)) 

Este será un poco más lento que el uso de funciones descubiertos porque de la búsqueda metatable Y no impedirá que nadie cambie el nombre de la función en el estado, cambie el nombre de la función en la tabla que lo contiene, cambie la función, etc., para que no sea a prueba de manipulaciones. También podría quitar las tablas simplemente indexando como fun1.fun, lo que podría ser bueno si lo exporta como un módulo, pero pierde los nombres y otros trucos que podría poner en la metatabla.

+0

Es cierto que la función es un valor, pero eso no significa que no pueda ser un valor compuesto, teniendo el código de la función y un nombre como metadatos asociados. Entiendo que es solo el modo Lua: cada función definida es solo una lambda almacenada en una tabla con la clave que la definición de función nombra: "La instrucción función f() cuerpo final se traduce en f = función() extremo del cuerpo ", según la referencia de Lua – Paralife

+2

cierto, pero esa clave no tiene que ser una cadena. Lo siguiente es completamente correcto en Lua: 't = {[function() print'foo 'end] = function() print'bar'end, {} = function() print'baz'end}' Así que aquí están las teclas respectivamente funciones y tablas. Dicho esto, la tabla contiene las funciones, y no al revés. Puede adjuntar metadatos a una función, pero siempre será "externa, como en los ejemplos que di. En Lua, una función no es un valor compuesto, es solo la función, ya que se ajusta a la filosofía de Lua de entregar las herramientas que permiten construyendo cualquier cosa – jpjacobs

+0

cierto, y no tengo nada más que añadir :) – Paralife

0

Prueba esto:

http://pgl.yoyo.org/luai/i/tostring

toString (x) con suerte debe ser lo que usted está buscando

+1

Estaba escéptico de que esto funcione, así que lo probé, y parece que no: http://codepad.org/uaZ2zSXW – delnan

+0

Oh, admití que estaba presumiendo un poco .. :( – Hybrid

+0

string.format tampoco funciona. No parece haber ninguna opción de formato adecuada ... – Paralife

0

Si No me equivoco (y probablemente lo haré, porque en realidad nunca programé en Lua, solo leí un montón de documentos y artículos), internamente ya hay una tabla con nombres de funciones (como locals y globals en Python), por lo tanto, debería poder realizar una búsqueda inversa para ver qué tecla coincide con una referencia de función.

De todos modos, solo especulando.

Pero el hecho es que al mirar su código, ya conoce el nombre de las funciones, por lo que puede construir la tabla. Si quiere ser menos propenso a errores, sería más fácil usar el nombre de la función para obtener la referencia de función (con eval o algo así) que al revés.

+0

Tienes razón, pero después de investigarlo, lo más cercano que pude encontrar es la función debug.getinfo. Pero no devuelve el nombre. la tabla global no menciona las funciones locales. Todavía estoy buscando una forma de introspección para adquirir el nombre del objeto, o como dijiste, al revés: el objeto del nombre. Pero hasta ahora no ha habido suerte. – Paralife

+1

Valor de una función puede tener muchos nombres, o ninguno. – lhf

1

Técnicamente esto es posible, aquí es una implementación de la función de exportación():

function export(...) 
     local env = getfenv(2); 
     local funcs = {...}; 
     for i=1, select("#", ...) do 
       local func = funcs[i]; 
       for local_index = 1, math.huge do 
         local local_name, local_value = debug.getlocal(2, local_index); 
         if not local_name then 
           break; 
         end 
         if local_value == func then 
           env[local_name] = local_value; 
           break; 
         end 
       end 
     end 
     return env; 
end 

Utiliza el debug API, requeriría algunos cambios para Lua 5.2, y, finalmente, que no necesariamente avala como una Una buena forma de escribir módulos. Simplemente estoy respondiendo la pregunta de manera bastante literal.

Cuestiones relacionadas