Front page | perl.perl5.porters |
Postings from May 2012
Re: Objects without stashes?
From: Stevan Little
May 25, 2012 16:33
Re: Objects without stashes?
Message ID: BC70CF2C-58E8-4330-838D-B3DDEE4CE785@iinteractive.com
On May 25, 2012, at 10:47 AM, Leon Timmermans wrote:
> I hate the way classes/objects work. In particular, I think stashes of
> globs of other stuff is paradigm that fails, and I don't think I stand
> alone in that. We all know how much effort it is to work with them,
> even when abstractions are available that make them less inconvenient.
> It makes me wonder why we're sticking to it so badly? Perl has always
> had a very minimalistic definition definition of what an object is. To
> quote perltoot:
>> An object is different from any other data type in Perl in one and only one way: you may dereference it using not merely string or numeric subscripts as with simple arrays and hashes, but with named subroutine calls. In a word, with methods.
> There is nothing, absolutely nothing, about this that requires stashes
> (or for that matter, there's nothing that requires packages/classes
> either). What if we simply added a vtable to all objects when
> blessing? At its minimal, this vtable would only need to support two
> methods: fetchmethod and ref, though more may be prudent (meta would
> be an obvious one, clone and destroy may be useful too). I think this
> would allow us to add new paradigms in a sensible and extensible way,
> without breaking too many other things.
So, I agree with everything you are saying, and actually this is very similar to the core instance type we are working on in the p5-mop project. If you distill down OO to its very essence you basically need two things. First is an instance type, something that can store instance scoped data, and second is a way to dispatch code (notice I didn't say method here) dynamically to an invocant (which itself is an instance type). Once you have these two things, you can build an entire object system on top of it (class based, prototype based, whatever).
To discuss your specific proposal, to start with, I like it, it removes a chunk of semi-ugly magic we are doing in the p5-mop to get dispatchable objects. I have a few concerns, all of which I think can be worked around.
I think you might run into a circularity issue with fetchmethod and ref being actual methods (how can fetchmethod fetch fetchmethod?), but this is the compromise of bootstrapping, so perhaps you make this a function call instead, after which you can make a method called fetchmethod that could call it (with some protections for infinite looping of course). We actually do something like this in the p5-mop internals for executing methods  but it does get a little messy (and mind-numbing at times).
Inheritance can be tricky, so either the vtable structure itself needs to know about it (which is the case with most vtable implementations) or the vtable needs to get locked at some point so that it can flatten out the inheritance hierarchy. Again, we are doing something similar in the p5mop in how we are using Package::Anon .
I don't think a meta method is needed, that can be lashed on via some kind of object system bootstrap, clone probably could be implemented in user-space as well, but destroy makes me wonder. It requires a knowledge about the outside scope that user-space code won't have. My only word of caution here is that destroy methods might be a slippery slope of infinitely recursive recursion, so might be best to handle it similar to how fetchmethod and ref would be handled.
Okay, thats my two cents. Thanks for including me in the CC.
 The core code is here (https://github.com/stevan/p5-mop/blob/master/lib/mop/internal/instance.pm) and I would expect if this were ever to make it into the core would be part of something like a MV (Method) structure and just be how the method is executed. Then in order to make Method::execute work in the MOP and to actually make it override able (because what good is a MOP if you can't totally muck with guts in that way) we do some manual "surgery" here (https://github.com/stevan/p5-mop/blob/master/lib/mop/bootstrap.pm#L111). The result is you get the ability to do insanity like this (https://github.com/stevan/p5-mop/blob/master/t/030-extensions/003-wrapping-methods.t) if you want too.
 we create/fetch a stash for each class from here (https://github.com/stevan/p5-mop/blob/master/lib/mop/internal.pm#L81) and then in the FINALIZE event of the Class object we populate the stash with a completely flattened method table (https://github.com/stevan/p5-mop/blob/master/lib/mop/bootstrap.pm#L405).