I've made a little mechanism for creating 2-D vectors in Lua. Vectors have two components i and j, and support addition, dot product, magnitude, and conversion to strings.Vector = {  new = function (i, j)    return setmetatable({i = i, j = j}, {      __index = Vector,      __add = function (self, v)        return Vector.new(self.i + v.i, self.j + v.j)      end,      __mul = function (self, v)        return self.i*v.i + self.j*v.j      end,      __tostring = function (self)        return string.format('<%g,%g>', self.i, self.j)      end    })  end,  magnitude = function (self)    return math.sqrt(self.i*self.i + self.j*self.j)  end}u = Vector.new(3, 4)v = Vector.new(-5, 10)print(u.i)print(u.j)print(u:magnitude())print(u + v)print(u * v)While I get expected results, I don't like the fact that each time I create a vector table, a brand new metatable is created. It would be nice to only have one metatable for all vectors. Also if there any non-idiomatic aspects to the code, those would be nice to know about as well.
Creating 2D vectors
lua;coordinate system;meta programming
I would recommend creating a separate module/package for the Vector types.Create a file named vector.lua. It'll return the custom Vector data structure.Use a local do...end block to wrap your meta-table. This will make the meta table private.magnitude is basically square-root of the result from self * self. Use this. ;-)I prefer to use __call meta-method instead of writing a new .new call. This is of course a personal preference.The resulting vector.lua would be like:local Vector = {}do    local meta = {        _metatable = Private metatable,        _DESCRIPTION = Vectors in 2D    }    meta.__index = meta    function meta:__add( v )        return Vector(self.i + v.i, self.j + v.j)    end    function meta:__mul( v )        return self.i * v.i + self.j * v.j    end    function meta:__tostring()        return (<%g, %g>):format(self.i, self.j)    end    function meta:magnitude()        return math.sqrt( self * self )    end    setmetatable( Vector, {        __call = function( V, i ,j ) return setmetatable( {i = i, j = j}, meta ) end    } )endVector.__index = Vectorreturn VectorNow, to use it as a package, just put a require call:local Vector = require 'vector'u = Vector(3, 4)v = Vector(-5, 10)