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