classの記述を簡潔に書けるようにする

Codifyでclassを記述する時の方法が以下の様な感じで、metatableを意識しないで書けるのがとても良かったので実装してみた。

Vec3 = class()
function Vec3:init(x,y,z)
	self.x,self.y,self.z = x,y,z
	print("vec3:init",x,y,z)
end
function Vec3:dump()
	print("vec3:dump",self.x,self.y,self.z)
end
function Vec3:set3(x,y,z)
	self.x,self.y,self.z = x,y,z
	print("vec3:set3",self.x,self.y,self.z)
end


Vec4 = class(Vec3)
function Vec4:init(x,y,z,w)
	self.x,self.y,self.z,self.w = x,y,z,w
	print("vec4:init",x,y,z,w)
end
function Vec4:dump()
	print("vec4:dump",self.x,self.y,self.z,self.w)
end


local v4_1 = Vec4(3,2,1,0)
local v3_1 = Vec3(4,5,6)
local v4_2 = Vec4(0,1,1,0)
local v3_2 = Vec3(7,8,9)

v4_1:set3(2,2,2)
v4_1:dump()
v4_2:dump()
v3_1:dump()
v3_2:dump()


__callを使えば出来そうって所までは直ぐに気がついたけど、__callの第一引数に呼び出した際のテーブルも一緒に渡されて来るのが分からなくて微妙にハマった。
Luaのマニュアル読んでもそんな事一ミリも書かれてないし。。。


可変引数でググッたらselect文を使えば良いよと書いてあったのでそうしてみた。

select(x,...)

x番目以降の可変引数が戻り値で返せるらしい。
以前のバージョンだと配列としてアクセスする方法があったような気がするんだけど無くなってしまったのか。


実装してみたら意外とシンプルに収まった。

function class(parent)
	local base = {
	}
	local mt = {
		__call = function(...)
			local mt = setmetatable({},{__index=base})
			mt.init(mt,select(2,...))
			return mt
		end
	}
	if (parent) then mt.__index = parent end
	
	return setmetatable(base,mt)
end

さり気なくクロージャーが生かされているのが渋い。
クロージャー使わなくても出来る方法があるような気がしないでもない。