clasp - tiny class library

evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

clasp - tiny class library

Yes, yes I know, there are a ton of class libraries out there, some good, some bad, to each their own. None of them quite felt good to me, so I made my own. This is a simple and clean class library. It uses c-style syntax and, while I know this is Lua and some may scream at this heresy, I think it looks better than adhering to Lua's functionlike approach (although you can still use it).

It does simple singular inheritance and metamethods declaration in class (using a separate table). No super, instead you call superclass methods explicitly, passing self as first argument.

Here's the github link and usage: https://github.com/evolbug/lua-clasp

Code: Select all

class = require "clasp"

-- Basic class
Vector = class {
isVector = true; -- static values
init = function(self, x, y) -- initializer function
self.x = x
self.y = y
end;
}
a = Vector(10, 10)
print('Vector:', a.x, a.y, a.isVector) -- "Vector: 10 10 true"


Code: Select all

-- Inheritance
Vector3 = Vector:extend {
init = function(self, x, y, z) -- function overriding
Vector.init(self, x, y) -- superclass method call
self.z = z
end;
}
b = Vector3(1, 2, 3)
print('Vector3:', b.x, b.y, b.z, b.isVector) -- "Vector3: 1 2 3 true"


Code: Select all

-- Metamethods
Point = class {
init = function(self, x, y)
self.x, self.y = x,y
end;
__ = { -- metamethod table
tostring = function(self)
return 'Point('..tostring(self.x)..', '..tostring(self.y)..')'
end;
};
}
c = Point(15, 25)
print(c) -- "Point(15, 25)"
Last edited by evölbug on Tue Apr 25, 2017 7:14 pm, edited 2 times in total.

airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: clasp - 13 lines of class

Not bad, looks similar to a solution I've used before (particularly "extend"). A few thoughts:

- Setting everything to weak keys seems suspicious/unnecessary, why do that?
- Calling pairs every time you instantiate a class is slow, can that be moved to declaration from instantiation?
- The js-style constructors that can return something other than the instance are interesting, be sure to document that behavior.
- Maybe add something like members = members or {} to also support the "not-c-style" more cleanly.

Regarding "pairs," you could get rid of it by using _meta as the metatable instead of copying everything over.

Code: Select all

local meta = self.__meta or {}
meta.__index = self

evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

- Setting everything to weak keys seems suspicious/unnecessary, why do that?
I saw some class library use weak keys, so I put them in too, dunno if it changes much really, removed it because keeps the code shorter
- Calling pairs every time you instantiate a class is slow, can that be moved to declaration from instantiation?
pairs() is called only for and if metamethods are defined in the class, and no it can't be moved, copying is necessary or it creates a metatable mess. haven't figured out how to do it without pairs yet, and why the mess is created otherwise
- The js-style constructors that can return something other than the instance are interesting, be sure to document that behavior.
they don't return anything, constructor - init() is called by new class system function and disregards it's return value. I noticed the problem in the code and fixed
- Maybe add something like members = members or {} to also support the "not-c-style" more cleanly.

evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

here's visible difference in using copying(current method) vs referencing (suggested) respectively
difference.png (9.76 KiB) Viewed 3931 times
the problem makes itself apparent when inheriting which is shown above

airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: clasp - 13 lines of class

Not sure how that happened, I just tried this and it seems to work ok:

Code: Select all

return function (members)
local cls = {}
function cls.new (self,...)
local meta = self.__meta or {}; meta.__index = self; self.__meta = nil -- this changed
local object = setmetatable({}, meta)
return object.init and object:init(...) and object or object
end
function cls.extend(base,members) return setmetatable(members,{__index=base,__call=cls.new}) end
return setmetatable(members or {},{__index=cls,__call=cls.new})
end
Haven't inspected it closely though, just tested that it works with the __tostring example from the readme.

evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

well, it technically "works", but try using this dump method to check the resulting structure of an inheriting class

Code: Select all

function indent(depth)
local s = ''
for i=0,depth do s=s..'  ' end
return s
end

function dump(table, label, depth)
local depth = depth or -1
local label = label or tostring(table)

print(indent(depth)..label..' {')

for k,v in pairs(table) do
if type(v) == 'table' and depth<8 then
dump(v, k, depth+1)
elseif depth<8 then
print(indent(depth+1)..k..': '..tostring(v))
else
return
end
end
if getmetatable(table) then
dump(getmetatable(table), '__meta__', depth+1)
end

print(indent(depth)..'}')
end

airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: clasp - 13 lines of class

I get the exact same structure... https://hastebin.com/movahoyisi.lua

evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

that's because you aren't inheriting

airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: clasp - 13 lines of class

Ahh, I see what you mean. Try meta = rawget(self, '__meta') or {}

evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

rawget() doesn't work at all, in fact it breaks metamethods

Who is online

Users browsing this forum: No registered users and 29 guests