Page 2 of 3

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 7:31 pm
by airstruck
You're right, I just tried it. Also noticed __meta still appears in the dump even after nilling it (with all three methods); something's off.

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 7:37 pm
by evölbug
well, from the end user perspective it makes no difference functionally, perhaps i can make it use reference instead. it's just that i don't like recursing stuff as it opens the potential to be incredibly hard to debug.

though metatables are hard to debug in general, and i've also noticed it doesn't override metamethods when inheriting, oh no :(

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 7:39 pm
by evölbug
so i have discovered that nilling the __meta table is not a good idea, in any cases, so now it's a matter of choosing that little bit of performance at the risk of being potentially harder to debug, or cleanliness

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 7:45 pm
by evölbug
i'm choosing ease of debugging versus whatever that fractal of headache is
fractal.png
fractal.png (52.05 KiB) Viewed 5926 times

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 7:48 pm
by airstruck
Here's what I came up with, I've got to run but take a look:

Code: Select all

local function new (self, ...)
    local meta = self.__meta or {}; meta.__index = self; self.__meta = nil
    local object = setmetatable({}, meta)
    return object.init and object:init(...) and object or object
end

local function extend (base, members)
    return setmetatable(members, { __index = base, __call = new })
end

return function (members)
    return extend(members or {}, { new = new, extend = extend })
end
About nilling __meta, it doesn't always do anything because it might be getting it from __index (with inheritance). Also why rawget didn't work. It would be nice if you could put metamethods directly in class definition instead of in __meta, that way subclass can override one metamethod while leaving others intact.

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 7:51 pm
by evölbug
it's the same as my code just spread out, and it still makes fractals when removing self.__meta = nil on line 2

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 8:02 pm
by airstruck
evölbug wrote:it's the same as my code just spread out
That was the point, still 13 lines but without redefining functions each time, also easier to follow I think.
it still makes fractals when removing self.__meta = nil on line 2
It gives an almost identical result to the "pairs" code when you don't remove that, though, doesn't it? But as you said I don't think there's any harm in leaving it there.

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 8:17 pm
by evölbug
well, it doesn't generate almost identical code, because you can't override individual methods without overriding whole __meta table, and also it generates fractals if you don't nil the table

Re: clasp - 13 lines of class

Posted: Sun Apr 23, 2017 8:22 pm
by evölbug
though your spread out approach inspired a more compact solution i have arrived at now

Re: clasp - 8 lines of class

Posted: Sun Apr 23, 2017 10:26 pm
by airstruck
Yeah, I see what you mean about overriding individual metamethods. I guess you'll need to copy these no matter what if they're supposed to be inherited. Here's an idea for moving it from instantiation to declaration:

Code: Select all

local function new (class, ...)
    local object = setmetatable({}, class)
    return object, object:init(...)
end

local function extend (class, proto)
    for k, v in pairs(class) do
        if k:match '^__' and proto[k] == nil then proto[k] = v end
    end
    proto.__index = proto
    return setmetatable(proto, class)
end

local base = { __call = new, new = new, extend = extend, init = function()end }
base.__index = base

return function (proto)
    return extend(base, proto)
end
This also lets you put your metamethods right in the class definition instead of a separate table. It will create lots of circular references from metatables being their own index, so the dump will be ugly. Can have dump function leave out cycles to get a better look; cycles in the dump are probably nothing to worry about.

Also has weird side effect that instances can themselves be extended and instantiated, but this could actually be pretty useful and sort of makes sense for prototype-based inheritance.