Front page | perl.perl5.porters |
Postings from November 2003
Re: [5.8.12] Proposal for changing UNIVERSAL semantics
Thread Previous
|
Thread Next
From:
Michael Jacob
Date:
November 4, 2003 06:05
Subject:
Re: [5.8.12] Proposal for changing UNIVERSAL semantics
Message ID:
GMail.1067952902.32427346.405430036647@smtp.youvegotpost.com
On 2003-11-04 01:08:32 Michael G Schwern <schwern@pobox.com> was overheard saying:
---------------------------------------------------
> my $code_ref = $class->can('can');
Add a "use UNIVERSAL qw( :canAsInPerl58 );" to the program that require an old module. Then this will work again and other modules will fail again if there is something unexpected in UNIVERSAL::.
>Backwards compatibility does not just mean your car goes in reverse.
If cars would use that kind of backward compatibility, a car with an automatic gear would still have a working third pedal and a working switching lever (4 forward gears and a second lever for using the fifth gear) and you would use the automatic by using a new button to switch it into automatic mode every time you start it.
>> or fail miserably when UNIVERSAL.pm is loaded or UNIVERSAL:: is modified.
>
>We do? I've been using can() for all sorts of horrid things for years and
>never had to do *that*. Why would I want to deliberately ignore methods
>inherited from UNIVERSAL?
Yes, I'd had a look at the modules.
Let's use an example:
Alice writes a module Alica::ParseXML that uses UNIVERSAL::monkier and published it to CPAN.
Bob writes the Modules Bob::Animal and Bon::Animal::Apes and published it to CPAN.
Caroll writes a program that uses both modules.
Do you see the naming problem? Ok, constructed pun here, but it's just an example...
sub Bob::Animal::whatever {
if shift->can('monkier') {
print "This animal can act monkier than a monkey";
>Are you saying we can't rely on UNIVERSAL.pm not being modified... when,
>at run time? Sometime in the future? I don't understand.
after we put our module to CPAN and some other programmer used it. When Caroll reports the bug to Bob he will be completly puzzled, because ha cannot find any bug in his code...
>Your code examples seem to imply that anything inherited from UNIVERSAL
>is inherited by mistake and must be covered up. That runs directly against
No, it's not inherted by mistake, the test for it returns true (any coderef is true) by mistake. Neither programmer X who write "bar->can('foo')" nor programmer Y who did not write "sub bar::foo" nor programmer Z who wrote "sub UNIVERSAL::foo" expected bar->can() to return true here.
Programmer Z expected bar->foo() to call "UNIVERSAL::foo(bar)", but he has no reason to ever can() for it. Nor has the Programmer C---after a use Zs::Code there is no need to can() for foo...
>the current uses of UNIVERSAL:: on CPAN. UNIVERSAL::monkier,
Doesn't need to can() for. Works without can() just as good.
>UNIVERSAL::require and
Seems to be broken the same way as UNIVERSAL.pm. Sorry.
>UNIVERSAL::exports. They all quite deliberately
Works without can('exports') reporting it, too.
>put perfectly normal public methods into UNIVERSAL.
Yes, that's what I also say. It is ok to add whatever to UNIVERSAL. But, if some programmer asks what object/class X can() he will not expect to find our new methods.
If you put a comment() method into UNIVERSAL you will find it called from XML::SAX while parsing. Huh? That is because XML::SAX looks with can() on its handlers to see if thex are interested on comment() calls. If not, it won't call comment(). But now can() always returns a coderef. And that coderef is not interested to be called by a module that did not know in advance that it is there.
>I think the problem is only triggered by Attribute::Handlers which, as
You're right, I didn't dive into DBI after that many modules broke on UNIVERSAL.pm and Attribute::Handlers.
>> In future, one who rally want's to catch _soft_referenced_method_calls_ to can(), is() and VERSION() must write:
>
>What's a soft_referenced_method_call?
$y = 'y'; $a = $x->can($y); $x->$y();
as opposed to real soft references:
$y = 'y'; $x->$y();
and hard references:
$y = \&x::y; $x->$y();
and normal method calls:
$x->y();
The other 3 can be done always, they don't need can(). So a wanted to make clear that we would only break modules doing a seldom used contruct on one of exactly three method names.
>> if (my $a = $obj->can($method) || UNIVERSAL->can($method)) {
>>
>> Tell me what more more often will be written as "$obj->can($method)" by accident?
I don't think so. As I pointed out in above example, the test for a method inherted from UNIVERSAL will usually not be what the programmer wants. Calling that method on the other hand will usually be, but there's no can needed. After the "use UNIVERSAL::modifying::module", we can just call A::B::C->buh() without testing for it first.
Michael
--
Gratuitous Advertisements:
This email was brought to you by You've Got Post!
http://www.youvegotpost.com
--
Publish your company's press releases for just $5.99 per month (unlimited access), visit http://www.officialspin.com
Thread Previous
|
Thread Next