venir publicos por larez lares etimologia estos distintos lua

publicos - ¿Cuál es la diferencia entre estos dos ejemplos de Lua? ¿Es uno mejor?



lares publicos (4)

Estoy empezando con Lua. En el ejemplo del que estoy aprendiendo ( fuente abierta Ghosts & Monsters Corona ), veo este patrón repetidamente.

local director = require("director") local mainGroup = display.newGroup() local function main() mainGroup:insert(director.directorView) openfeint = require ("openfeint") openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" ) director:changeScene( "loadmainmenu" ) return true end main()

¿Es esto algún tipo de convención que los programadores de Lua recomiendan o hay ventajas genuinas para hacerlo de esta manera? ¿Por qué no saltearías la función todos juntos y harías esto?

local director = require("director") local mainGroup = display.newGroup() mainGroup:insert(director.directorView) local openfeint = require ("openfeint") openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" ) director:changeScene( "loadmainmenu" )

¿Hay algún beneficio implícito para el primer estilo sobre el segundo? ¡Gracias!


¿Es esto algún tipo de convención que los programadores de Lua recomiendan o hay ventajas genuinas para hacerlo de esta manera?

No es típico. La ventaja es que el estado del objeto es privado, pero eso no es suficiente como para recomendarlo.

Veo este patrón repetidamente.

Nunca lo había visto antes, y solo ocurre una vez en la fuente que publicaste.

EDITAR: Agregar una respuesta a una pregunta formulada en los comentarios debajo de esta publicación.

Una función que accede a variables locales externas se une a esas variables y se denomina ''cierre''. Lua (por razones históricas) se refiere a esas variables vinculadas como ''valores ascendentes''. Por ejemplo:

local function counter() local i = 1 return function() print(i) i = i + 1 end end local a, b = counter(), counter() a() a() a() b() --> 1 2 3 1

b son cierres vinculados a diferentes copias de i , como se puede ver en la salida. En otras palabras, puede pensar en un cierre como función con su propio estado privado. Puedes usar esto para simular objetos:

function Point(x,y) local p = {} function p.getX() -- syntax sugar for p.getX = function() return x end function p.setX(x_) x = x_ end -- for brevity, not implementing a setter/getter for y return p end p1 = Point(10,20) p1.setX(50) print(p1.getX())

Point devuelve una tabla de cierres, cada uno vinculado a los locales y . La tabla no contiene el estado del punto, los cierres sí lo hacen, a través de sus valores ascendentes. Un punto importante es que cada vez que se llama a Point , crea nuevos cierres, lo que no es muy eficiente si tiene grandes cantidades de objetos.

Otra forma de crear clases en Lua es crear funciones que tomen una tabla como primer argumento, con estado almacenado en la tabla:

function Point(x,y) local p = {x=x,y=y} function p:getX() -- syntax sugar for p.getX = function(self) return self.x end function p:setX(x) self.x = x end return p end p1 = Point(10,20) p1:setX(50) -- syntax sugar for p1.setX(p1, 50) print(p1:getX()) -- syntax sugar for p1.getX(p1)

Hasta ahora, seguimos creando nuevas copias de cada método, pero ahora que no confiamos en los valores de estado, podemos solucionarlo:

PointClass = {} function PointClass:getX() return self.x end function PointClass:setX(x) self.x = x end function Point(x,y) return { x = x, y = y, getX = PointClass.getX, setX = PointClass.getY, } end

Ahora los métodos se crean una vez y todas las instancias Point comparten los mismos cierres. Una forma aún mejor de hacerlo es utilizar la función de metaprogramación de Lua para hacer que las nuevas instancias de Point se vean automáticamente en PointClass para los métodos que no se encuentran en la instancia en sí:

PointClass = {} PointClass.__index = PointClass -- metamethod function PointClass:getX() return self.x end function PointClass:setX(x) self.x = x end function Point(x,y) return setmetatable({x=x,y=y}, PointClass) end p1 = Point(10,20) -- the p1 table does not itself contain a setX member, but p1 has a metatable, so -- when an indexing operation fails, Lua will look in the metatable for an __index -- metamethod. If that metamethod is a table, Lua will look for getX in that table, -- resolving p1.setX to PointClass.setX. p1:setX(50)

Esta es una forma más idiomática de crear clases en Lua. Es más eficiente en cuanto a la memoria y más flexible (en particular, facilita la implementación de la herencia).


Con frecuencia escribo mis propios guiones Lua de esta manera porque mejora la legibilidad en este caso:

function main() helper1( helper2( arg[1] ) ) helper3() end function helper1( foo ) print( foo ) end function helper2( bar ) return bar*bar end function helper3() print( ''hello world!'' ) end main()

De esta forma, el código "principal" está en la parte superior, pero aún puedo definir las funciones globales necesarias antes de que se ejecute.

Un truco simple, realmente. No puedo pensar en ninguna razón para hacer esto además de la legibilidad.


El primer estilo se puede utilizar también legibilidad improove, pero prefiero darle a la función un nombre significativo en lugar de main o simplemente ir sin la función.

Por cierto, creo que siempre es una buena práctica nombrar bloques de código, es decir, ponerlos en funciones o métodos. Ayuda a explicar tu intención con ese fragmento de código y fomenta la reutilización.


No veo mucho que apunte al primer estilo como lo has mostrado. Pero si dijera algo así como if arg then main() end en la parte inferior, el script podría (simplemente podría) ser útil como una "biblioteca" cargable además de ser un script independiente. Dicho eso, tener un main() como ese huele a C, no a Lua; Creo que tienes razón para cuestionarlo.