Jan Ingvoldstad wrote:
On Thu, Aug 20, 2009 at 10:44 PM, Kevan Benson <kben...@a-1networks.com>wrote:

That said, I submit that it's a very confusing part of the language as
defined currently, and I haven't seen a very thorough explanation of the
purpose of each method in the chain the instantiates a new object.  S12
touches upon them slightly, but not in enough detail that I was able to work
out where I should be adding code to appropriately make alternate
constructors.


Now that you apparently understand it, do you have a suggestion on how S12
might be phrased differently?

I must admit that I don't quite grasp the concepts here yet, so an alternate
wording might help others as well.

Thanks for bringing the question up.

Unfortunately I'm not at all confident I do understand it all, but I'll explain how I think it works and people more knowledgeable than me will hopefully step in and explain where I'm wrong. Maybe out of this we can get some consensus on what needs to be added WRT object constructors in S12.

The creation sequence looks something like this:
.new(args) {
        my $self = .bless(class,  {
                .BUILDALL(class, args) {
                        # in reverse MRO
                        for (@parent) { .BUILD(class, args) }
                        .BUILD(class, args)
        }
}

Note: Actually, I believe the current .BUILD is actually called as part of the call to all parent .BUILD methods in Rakudo. At least that's what I'm able to infer from the parrot code for Rakudo objects at src/classes/Object.pir starting at line 272 (thanks japhb!).

.new - Handles the actual call to .new from code, define other submethods/methods for this if you want to create alternate constructors. You should normalize all paramaters to named values before calling .bless. S12 implies that any .new you write (or a constructor of any other name you define) must call .bless.

.bless - See S12 (http://perlcabal.org/syn/S12.html#Construction_and_Initialization) for more info, but this is responsible for actually creating the object (unless .CREATE called before and opaque object passed) and calling the BUILD routines.

.BUILDALL - If it's still valid, http://dev.perl.org/perl6/rfc/189.html seems to cover the expected behavior of this.

.BUILD - Used for object initialization, assigning passed named values (pairs) to object attributes if they match, or doing something more complex to initialize the object correctly based on supplied data.


Some things to be wary of or that I'm still hazy on:

What sort of calling syntax can be used in .new since the object isn't yet blessed? Or since .new encapsulates .bless (right?), I guess you can call normally AFTER the bless.

.new happens before calling parent constructors, .BUILD happens after, so .new possibly won't have access to some default attributes as defined by parent classes/roles.

Theoretically you could define a custom constructor, normalize data, call the regular .new constructor, and post process on the object returned before returning it yourself, I think.

--

-Kevan Benson
-A-1 Networks

Reply via email to