moduleluametatable

(Lua) Simple metatable in another file


I'm sorry that it is such a basic issue but I can't seem to understand. I'm a beginner in Lua and so I have several questions.

My goal is to make a small "class" Vector3. I'm using a metatable that I put in a file vector3.lua.

1) Since my metatable Vector3 is in a separate file from my main.lua, am I correct to assume I am writing a "module" ? Is it really different from putting my code in the same file as my main ?

1.5) If I am writing a module, is there a way to create a function "new" to use this syntax in the main :

v = Vector3(3, 2, 4)

assuming I'm importing my vector3.lua as

local Vector3 = require "Vector3"

?

2) Do all modules require

return Vector3

at the end of the module ? Why ?

3) Finally, I am unable to understand my compiling error. Those are my files :

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() -- this is my 8th line in my editor (the error line)
    return "(x:" .. self.x .. ", y:" .. self.y .. ", z:" .. self.z .. ")"
end

local function Vector3.__newindex()
    print("You cannot add another axis to a vector3")
end

return Vector3

and main.lua

local Vector3 = require "Vector3"

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

print(v)

and my 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 ?

What could be the issue ?

4) And even if I comment my :__tostring() and .__newindex functions, this is another error I get :

$ 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 ?

Is this another problem or is it because my metatable has no function (overwritten (I'm thinking about __add, etc) or not) other than new ?

Thank you for your time !


Solution

  • For future notice, you should have asked each of these question in a separate post.

    1. putting the coding in a separate file make is easier to reuse and to encapsulate your class.

      1.5 define __call metatable and have it call new

    2. it is best practice to define as local in the module file, and then return that value at the end of the file to prevent global name collisions, allow the caller to make the choice of the name.

    3. you have to define a function like function Vector3:__tostring() when using a table, you can't use local (also it just unnecessary since the function will be contained within the table).

    4. you forgot to define new as part of your vector class Vector3.new