Re: Test::Aggregate and UNIVERSAL::can
I mentioned that we removed UNIVERSAL::can because of bugs introduced by global behavior changes, but to be fair to chromatic, I should explain that this is because of code in Template::Timer: perl -MUNIVERSAL::can -MTemplate::Timer -e 1 Died at lib/perl5/Template/Timer.pm line 63. Compilation failed in require. BEGIN failed--compilation aborted. The problem is this line in Template::Timer: my $super = __PACKAGE__-can(SUPER::$sub) or die; This is OO code and that should actually read: my $super = __PACKAGE__-can($sub) or die; That makes the problem go away. Barring a local fix or the author fixing this, eliminating UNIVERSAL::can made the problem go away. David Wheeler reported this problem earlier at http://rt.cpan.org//Ticket/Display.html?id=16805 Cheers, Ovid -- Buy the book - http://www.oreilly.com/catalog/perlhks/ Perl and CGI - http://users.easystreet.com/ovid/cgi_course/ Personal blog - http://publius-ovidius.livejournal.com/ Tech blog - http://use.perl.org/~Ovid/journal/
Re: Test::Aggregate and UNIVERSAL::can
On 03/01/2008, Ovid [EMAIL PROTECTED] wrote: I mentioned that we removed UNIVERSAL::can because of bugs introduced by global behavior changes, but to be fair to chromatic, I should explain that this is because of code in Template::Timer: perl -MUNIVERSAL::can -MTemplate::Timer -e 1 Died at lib/perl5/Template/Timer.pm line 63. Compilation failed in require. BEGIN failed--compilation aborted. The problem is this line in Template::Timer: my $super = __PACKAGE__-can(SUPER::$sub) or die; This is OO code and that should actually read: my $super = __PACKAGE__-can($sub) or die; Er, i dont see how it could. Then $super would have a reference to its own method and not its parents. Yves -- perl -Mre=debug -e /just|another|perl|hacker/
Re: Test::Aggregate and UNIVERSAL::can
--- demerphq [EMAIL PROTECTED] wrote: The problem is this line in Template::Timer: my $super = __PACKAGE__-can(SUPER::$sub) or die; This is OO code and that should actually read: my $super = __PACKAGE__-can($sub) or die; Er, i dont see how it could. Then $super would have a reference to its own method and not its parents. I should have posted more context. What's happening is that Template::Timer inherits from Template::Context and that line merely checks that two methods which it inherits actually are available. If they are, it wraps them in timing code. It does *not* implement those methods directly so it can't have a reference to its own method. An alternative would be to do search @ISA or refer to the base class directly: my $super = Template::Context-can($sub) or die; That's a bit ugly and not really in the OO spirit, but it also works around the fact that it doesn't play well with UNIVERSAL::can. Cheers, Ovid -- Buy the book - http://www.oreilly.com/catalog/perlhks/ Perl and CGI - http://users.easystreet.com/ovid/cgi_course/ Personal blog - http://publius-ovidius.livejournal.com/ Tech blog - http://use.perl.org/~Ovid/journal/
Re: Test::Aggregate and UNIVERSAL::can
On 3 Jan 2008, at 16:55, Ovid wrote: my $super = __PACKAGE__-can(SUPER::$sub) or die; This is OO code and that should actually read: my $super = __PACKAGE__-can($sub) or die; Should that be __PACKAGE__-SUPER::can($sub) ? -- Andy Armstrong, Hexten
Re: Test::Aggregate and UNIVERSAL::can
On 03/01/2008, Ovid [EMAIL PROTECTED] wrote: --- demerphq [EMAIL PROTECTED] wrote: The problem is this line in Template::Timer: my $super = __PACKAGE__-can(SUPER::$sub) or die; This is OO code and that should actually read: my $super = __PACKAGE__-can($sub) or die; Er, i dont see how it could. Then $super would have a reference to its own method and not its parents. I should have posted more context. What's happening is that Template::Timer inherits from Template::Context and that line merely checks that two methods which it inherits actually are available. If they are, it wraps them in timing code. It does *not* implement those methods directly so it can't have a reference to its own method. An alternative would be to do search @ISA or refer to the base class directly: my $super = Template::Context-can($sub) or die; That's a bit ugly and not really in the OO spirit, but it also works around the fact that it doesn't play well with UNIVERSAL::can. This is all strange, but now i understand what you mean. Thanx. Yves -- perl -Mre=debug -e /just|another|perl|hacker/
Re: Test::Aggregate and UNIVERSAL::can
On 03/01/2008, Andy Armstrong [EMAIL PROTECTED] wrote: On 3 Jan 2008, at 17:20, Andy Armstrong wrote: my $super = __PACKAGE__-can($sub) or die; Should that be __PACKAGE__-SUPER::can($sub) ? Hmm. Does that do what I think it does? Maybe not. Without looking at the code we dont know whether the call is from within a method call. And thinking about it more i think that was the whole point of the weird call, Im guessing here, but probably this code isnt in a method which means that he doesnt have access to SUPER so, he passes it into can() which does. The following one liner demonstrates what the author of Template::Timer was (correctly) doing. Note that it doesnt matter if you define B::foo or not. $ perl -le'@B::ISA=qw(A); sub A::foo {print in A::foo} package B; sub foo {print in B::foo} __PACKAGE__-can(SUPER::foo)-();' in A::foo So assuming this code was NOT inside a method (most likely as he said it was part of code that installs methods) it looks like the code that Ovid bumped into was in fact correct, and chromatic's UNIVERSAL::can is broken with regard to SUPER::. And talking to yourself? What's all that about? Sometimes its hard to find decent conversation. :-) cheers, Yves -- perl -Mre=debug -e /just|another|perl|hacker/
Re: Test::Aggregate and UNIVERSAL::can
On Thursday 03 January 2008 09:58:28 demerphq wrote: And thinking about it more i think that was the whole point of the weird call, Im guessing here, but probably this code isnt in a method which means that he doesnt have access to SUPER so, he passes it into can() which does. The following one liner demonstrates what the author of Template::Timer was (correctly) doing. Note that it doesnt matter if you define B::foo or not. $ perl -le'@B::ISA=qw(A); sub A::foo {print in A::foo} package B; sub foo {print in B::foo} __PACKAGE__-can(SUPER::foo)-();' in A::foo Is that documented anywhere to work? I couldn't find it. In fact, it contradicts the documentation of can(): can checks if the object or class has a method called METHOD. If it does then a reference to the sub is returned. If it does not then undef is returned. This includes methods inherited or imported by $obj, CLASS, or VAL. -- c
Re: Test::Aggregate and UNIVERSAL::can
On 03/01/2008, chromatic [EMAIL PROTECTED] wrote: On Thursday 03 January 2008 09:58:28 demerphq wrote: And thinking about it more i think that was the whole point of the weird call, Im guessing here, but probably this code isnt in a method which means that he doesnt have access to SUPER so, he passes it into can() which does. The following one liner demonstrates what the author of Template::Timer was (correctly) doing. Note that it doesnt matter if you define B::foo or not. $ perl -le'@B::ISA=qw(A); sub A::foo {print in A::foo} package B; sub foo {print in B::foo} __PACKAGE__-can(SUPER::foo)-();' in A::foo Is that documented anywhere to work? I couldn't find it. In fact, it contradicts the documentation of can(): can checks if the object or class has a method called METHOD. If it does then a reference to the sub is returned. If it does not then undef is returned. This includes methods inherited or imported by $obj, CLASS, or VAL. Even if it isnt explicitly documented I take it as being implicitly documented by the fact that SUPER:: is documented (in perltoot at least) to have no meaning except inside of a method call. So if you arent inside of a method call how are you to get access to an objects overloaded method? And i dont think you don't is a good answer as its clearly useful to do in dynamically constructed classes. As for the documentation, ive probably been in front of this machine for too long today so im not seeing the contradiction. Are you basing this on the bit where it says 'called METHOD'? Personally I dont think that paragraph goes a long way towards settling things either way. OTOH Looking through the sources a bit it looks to me like this is pretty deliberate behaviour. UNIVERSAL::can() is just a wrapper around gv_fetchmethod_autoload() which is internally documented to respect SUPER::. Also consider the case of $obj-$method(). Unless we want $method='SUPER::foo'; $obj-can($method)-() to do something different than $method='SUPER::foo'; $obj-$method() I think it has to respect SUPER. I think when you add up the incidental evidence like things like above the only rational conclusion is that the native -can() *is* doing the right thing. Yves -- perl -Mre=debug -e /just|another|perl|hacker/
Re: Test::Aggregate and UNIVERSAL::can
On 3 Jan 2008, at 21:02, Aristotle Pagaltzis wrote: No. That calls `can` from the superclass, but passes `__PACKAGE__` as the invocant. Assuming that the subclass and the superclass use the same inherited `can` method, the result is therefore exactly the same. The correct incantation is my ( $super ) = grep { $_-can( $sub ) } @ISA; Yes, I realised that as soon as I posted - hence my mini debate with myself. Then I went and fixed the dodgy bit of code I'd just written that used exactly that idiom :) -- Andy Armstrong, Hexten
Re: Test::Aggregate and UNIVERSAL::can
On 03/01/2008, Aristotle Pagaltzis [EMAIL PROTECTED] wrote: * Andy Armstrong [EMAIL PROTECTED] [2008-01-03 18:25]: On 3 Jan 2008, at 16:55, Ovid wrote: my $super = __PACKAGE__-can(SUPER::$sub) or die; This is OO code and that should actually read: my $super = __PACKAGE__-can($sub) or die; Should that be __PACKAGE__-SUPER::can($sub) ? No. That calls `can` from the superclass, but passes `__PACKAGE__` as the invocant. Assuming that the subclass and the superclass use the same inherited `can` method, the result is therefore exactly the same. The correct incantation is my ( $super ) = grep { $_-can( $sub ) } @ISA; I think the correct thing is what kicked off this conversation. my $sub= __PACKAGE__-can(SUPER::$sub); Consider that with 5.10 its possible to use other method resolution rules than the one your snippet mimics. Yves -- perl -Mre=debug -e /just|another|perl|hacker/
Re: Test::Aggregate and UNIVERSAL::can
* demerphq [EMAIL PROTECTED] [2008-01-04 00:00]: Consider that with 5.10 its possible to use other method resolution rules than the one your snippet mimics. Does it change the MRO globally without regard for whether any loaded classes are prepared for that? Regards, -- Aristotle Pagaltzis // http://plasmasturm.org/