clasp - tiny class library

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

clasp - tiny class library

Post by evölbug »

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
wiki link too: https://love2d.org/wiki/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.
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: clasp - 13 lines of class

Post by airstruck »

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
User avatar
evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

Post by evölbug »

- 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.
added this one
User avatar
evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

Post by evölbug »

here's visible difference in using copying(current method) vs referencing (suggested) respectively
difference.png
difference.png (9.76 KiB) Viewed 7859 times
the problem makes itself apparent when inheriting which is shown above
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: clasp - 13 lines of class

Post by airstruck »

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.
User avatar
evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

Post by evölbug »

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
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: clasp - 13 lines of class

Post by airstruck »

I get the exact same structure... https://hastebin.com/movahoyisi.lua
User avatar
evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

Post by evölbug »

that's because you aren't inheriting
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: clasp - 13 lines of class

Post by airstruck »

Ahh, I see what you mean. Try meta = rawget(self, '__meta') or {}
User avatar
evölbug
Prole
Posts: 38
Joined: Wed Dec 21, 2016 12:58 pm
Contact:

Re: clasp - 13 lines of class

Post by evölbug »

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

Who is online

Users browsing this forum: No registered users and 43 guests