Moritz clarified:

> In BUILD, the object isn't yet fully constructed, and thus using $.attr
> (which is really a virtual method call in disguise) is wrong. STD and
> niecza already catch that at compile time, and I'm currently trying to
> make rakudo catch it too (branch 'has-self' on github).

Agreed. That example should certainly use $!attr instead.


> More to the point, objects are constructed by .new calling .bless, which
> in turn calls BUILDALL which finally calls BUILD. Since .bless only
> takes named arguments (besides the candidate to be blessed), how could
> BUILDALL know how to call BUILD with positional arguments?

Agreed. That example should be: submethod BUILD( :$arg ) {...}


> Finally Rakudo, Niecza and Pugs all agree that the default .new and thus
> .BUILD only take named arguments, and while that's not authoritative, it
> is a strong indicator that the example above contradicts the compiler
> writer's understanding of object initialization system.

Agreed. I dearly want BUILD to take only named args.


My point was that I don't want the named arguments that BUILD can take
to be restricted to only the names of public attributes...which was, I
thought, yary's complaint when writing:

>> If one wants to use any argument in the constructor other than a
>> public attribute (positional OR named other than an attribute name),
>> one must define a "method new( ... )".

If the complaint is that yary wanted to pass positional args to a
constructor, then I have no problem with having to write one's own
non-standard new() method to achieve that. If anything, we should make it
even harder than that. ;-)

But if one can't pass arbitrary named values to the standard new() and
have one (or more!) BUILD methods correctly use them, like so:

    class Date {
        has Num $!seconds_from_epoch;

        multi submethod BUILD (Str :$date) {
            $!seconds_from_epoch = _date_from_str($date);
        }

        multi submethod BUILD (Int :$year, Int :$month, Int :$day) {
            $!seconds_from_epoch = _date_from_YMD($year, $month, $day);
        }

        # etc.
    }

and then be able to call:

    my $today    = Date.new(date => 'Feb 2, 2012');
    my $tomorrow = Date.new(year => 2012, month => 2, day => 3);

then we've failed to make Perl 6 even as usable as C++, which is
a tragedy.

I sounds like I simply misunderstood yary's problem, but I'd be
very glad to be reassured that's the case. :-)

Damian

Reply via email to