ropa - lua tutorial
Número variable de argumentos de función Lua 5.1 (2)
En mi script de Lua, intento crear una función con una cantidad variable de argumentos. Por lo que sé, debería funcionar como a continuación, pero de alguna manera me sale un error con Lua 5.1 en el TI-NSpire (el argumento global es nulo). ¿Qué estoy haciendo mal? ¡Gracias!
function equation:init(...)
self.equation = arg[1]
self.answers = {}
self.pipe = {arg[1]}
self.selected = 1
-- Loop arguments to add answers.
for i = 2, #arg do
table.insert(self.answers, arg[i])
end
end
instance = equation({"x^2+8=12", -4, 4})
Tratar
function equation:init(...)
local arg={...}
La respuesta de Luis es correcta, si es más terser que un principiante del lenguaje. Trataré de explayarme un poco, con suerte, sin crear confusión adicional.
Su pregunta está en el contexto de Lua incrustado en un modelo específico de calculadora TI. Por lo tanto, habrá detalles que difieren de Lua independiente, pero la mayoría de esos detalles se relacionarán con las bibliotecas y funciones disponibles en su entorno. Es inusual (aunque desde Lua es de código abierto, posible) para las versiones integradas de Lua para diferir significativamente de la Lua independiente distribuida por sus autores. (The Lua Binaries es un repositorio de binarios para muchas plataformas. Lua para Windows es una distribución completa incluida en baterías para Windows.)
Su código de muestra tiene un factor de confusión, el detalle que necesita para interactuar con un sistema de clase proporcionado por el marco de la calculadora. Ese detalle aparece principalmente como una ausencia de conexión entre su objeto de equation
y la equation:init()
se llama a la función equation:init()
. Como hay técnicas que pueden pegar eso, es solo una distracción.
Tu pregunta tal como la entiendo se reduce a una confusión sobre cómo las funciones variadas (funciones con un número variable de argumentos) se declaran e implementan en Lua. De su comentario sobre la respuesta de Luis, ha estado leyendo la edición en línea de Programación en Lua (también conocida como PiL). Usted citó la sección 5.2 . PiL es una buena fuente de antecedentes sobre el lenguaje. Desafortunadamente, las funciones variadas son una de las características que ha estado en flujo. La edición del libro en línea es correcta a partir de Lua versión 5.0, pero la calculadora de TI probablemente ejecute Lua 5.1.4.
En Lua 5, se declara una función variadica con una lista de parámetros que termina con el símbolo ...
que representa el resto de los argumentos. En Lua 5.0, la llamada se implementó con una variable local "mágica" llamada arg
que contenía una tabla que contenía los argumentos que coincidían con ...
Esto requirió que cada función variad creara una tabla cuando se llama, que es una fuente de sobrecarga y presión innecesarias en el recolector de basura. Por lo tanto, en Lua 5.1, la implementación se modificó: el ...
se puede usar directamente en la función llamada como un alias de los argumentos coincidentes, pero no se creó realmente ninguna tabla. En cambio, si es necesario contar los argumentos, escriba select("#",...)
, y si desea el valor del enésimo argumento, escriba select(n,...)
.
Un factor de confusión en su ejemplo regresa al sistema de clase. Desea declarar la equation:init(...)
la función equation:init(...)
. Como esta declaración usa la sintaxis de dos puntos, es equivalente a escribir equation.init(self,...)
. Entonces, cuando se llama eventualmente a través del uso del __call
__call del __call
clase, el primer argumento real se llama self
y el cero o más argumentos reales coincidirán con ...
Como señala el comentario de Amr a continuación, la expresión select(n,...)
realidad devuelve todos los valores del enésimo argumento, que es particularmente útil en este caso para construir self.answers
, pero también conduce a un posible error en el inicialización de self.pipe
.
Aquí está mi aproximación revisada de lo que está tratando de lograr en su definición de equation:init()
, pero tenga en cuenta que no tengo una de las calculadoras de TI a mano y esto no se ha probado:
function equation:init(...)
self.equation = select(1, ...)
self.pipe = { (select(1,...)) }
self.selected = 1
self.answers = { select(2,...) }
end
En la versión revisada que se muestra arriba he escrito {(select(1,...))}
para crear una tabla que contiene exactamente un elemento que es el primer argumento, y {select(2,...)}
para crear una tabla que contiene todos los argumentos restantes. Si bien existe un límite en el número de valores que se pueden insertar en una tabla de esa manera, ese límite está relacionado con el número de valores de retorno de una función o el número de parámetros que se pueden pasar a una función, por lo que no se puede superado por la referencia a ...
Tenga en cuenta que este puede no ser el caso en general, y escribir { unpack(t) }
puede dar como resultado que no se copie toda la parte de la matriz de t
.
Una forma un poco menos eficiente de escribir la función sería escribir un ciclo sobre los argumentos pasados, que es la versión en mi respuesta original. Eso se vería así:
function equation:init(...)
self.equation = select(1, ...)
self.pipe = {(select(1,...))}
self.selected = 1
-- Loop arguments to add answers.
local t = {}
for i = 2, select("#",...) do
t[#t+1] = select(i,...)
end
self.answers = t
end