es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Metatabla simple en otro archivo (Lua)

Lo siento por tener un problema tan básico, pero no puedo entenderlo. Soy un principiante en Lua, por lo que tengo varias preguntas.

Mi objetivo es crear una pequeña “clase” Vector3. Estoy usando una metatabla que coloco en un archivo “vector3.lua”.

1) Dado que mi metatabla Vector3 está en un archivo separado de mi “main.lua”, ¿es correcto asumir que estoy escribiendo un “módulo”? ¿Realmente es diferente de poner mi código en el mismo archivo que mi main?

1.5) Si estoy escribiendo un módulo, ¿hay alguna manera de crear una función “new” para usar esta sintaxis en el main:

v = Vector3(3, 2, 4)

suponiendo que estoy importando mi “vector3.lua” como

local Vector3 = require"Vector3"

2) ¿Todos los módulos requieren

return Vector3

al final del módulo? ¿Por qué?

3) Finalmente, no puedo entender mi error de compilación.
Estos son mis archivos:

“vector3.lua”

local Vector3 = {} 
Vector3.__index = Vector3

local function new(x, y, z)
    return setmetatable( {x=x, y=y, z=z} , Vector3 )
end

local function Vector3:__tostring() -- esta es mi línea 8 en mi editor (la línea del error)
    return "(x:" .. self.x .. ", y:" .. self.y .. ", z:" .. self.z .. ")"
end

local function Vector3.__newindex()
    print("No puedes agregar otro eje a un Vector3")
end

return Vector3

Y “main.lua”

local Vector3 = require "Vector3"

v = Vector3.new(3, 2, 4)

print(v)

Y mi error:

$ lua main.lua
lua: error loading module 'Vector3' from file './Vector3.lua':
    ./Vector3.lua:8: '(' expected near ':'
stack traceback:
    [C]: in ?
    [C]: in function 'require'
    main.lua:1: in main chunk
    [C]: in ?

¿Cuál podría ser el problema?

4) Incluso si comento mis funciones :tostring() y .__newindex(), aquí está otro error que obtengo:

$ lua main.lua
lua: main.lua:3: field 'new' is not callable (a nil value)
stack traceback:
    main.lua:3: in main chunk
    [C]: in ?

¿Es este otro problema o es porque mi metatabla no tiene ninguna función (sobrescrita (estoy pensando en __add, etc.) o no) aparte de new?

¡Gracias por tu tiempo!

Tags:  , ,

Answer

  1. Avatar for davy.ai
    1. Sí, tienes razón. Al colocar tu metatabla en un archivo separado, estás creando un módulo Lua. Es diferente a poner tu código en el mismo archivo que tu programa principal porque te permite organizar y modularizar mejor tu código.

    1.5. Sí, puedes crear una función llamada “new” agregando el siguiente código al final de tu archivo vector3.lua:

    function Vector3.new(x, y, z)
      return setmetatable({x=x, y=y, z=z}, Vector3)
    end
    

    Esto te permitirá crear nuevas instancias de tu clase Vector3 utilizando la sintaxis que mencionaste en tu ejemplo.

    1. Sí, todos los módulos deben devolver un valor al final, en este caso, sería la tabla Vector3. Esto se debe a que cuando requieres un módulo, Lua espera que el módulo devuelva un valor. Al devolver una tabla, esencialmente estás devolviendo la interfaz de tu módulo.
    2. El problema con el código parece ser un error de sintaxis en la función __tostring. No puedes usar la notación : en funciones locales, solo en campos de tablas. Para solucionar este problema, debes reemplazar : por . de la siguiente manera:

    local function Vector3.__tostring(self)
      return "(x:" .. self.x .. ", y:" .. self.y .. ", z:" .. self.z .. ")"
    end
    
    1. El problema con este error es que tu tabla Vector3 no tiene un campo new que sea una función. Para solucionarlo, debes agregar la función new a tu tabla Vector3 de la siguiente manera:
    local Vector3 = {} 
    Vector3.__index = Vector3
    
    function Vector3.new(x, y, z)
      return setmetatable({x=x, y=y, z=z}, Vector3)
    end
    
    Vector3.__tostring = function(self)
      return "(x:" .. self.x .. ", y:" .. self.y .. ", z:" .. self.z .. ")"
    end
    
    Vector3.__newindex = function()
      print("No puedes agregar otro eje a un vector3")
    end
    
    return Vector3
    

    Al hacer esto, tu tabla Vector3 tendrá un campo new que es una función, por lo que podrás crear nuevas instancias de la clase utilizando la sintaxis Vector3.new.

Comments are closed.