Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Foo is not a Bar, why?

by liz (Monsignor)
on Dec 18, 2003 at 15:23 UTC ( [id://315535]=perlmeditation: print w/replies, xml ) Need Help??

A discussion on p5p the past day, lead me to a new insight that I would like to share with you. An insight that attempting to reduce a problem to a single set of lines, may sometimes backfire on you.

The problem can be shown by running the following lines:

my $foo = Foo->new; print "foo is".($foo->isa( 'Bar' ) ? '' : ' _not_')." a Bar\n"; package Bar; package Foo; @Foo::ISA = qw(Bar); sub new { bless {},shift } __END__ $foo is _not_ a Bar

You might wonder why does not produce the expected "$foo is a Bar" string.

It actually was Hugo van der Sanden on p5p who gave the solution, so I can't take any credit for that. The reason why: @Foo::ISA = qw(Bar) doesn't get executed until after the print with the ->isa check is executed. So at that time, the Foo package was indeed not yet inheriting from Bar.

As I said on p5p, this is when you realize that objects are bolted onto Perl 5.

And thus ends my meditation for today.

Liz

Replies are listed 'Best First'.
Re: Foo is not a Bar, why?
by PodMaster (Abbot) on Dec 18, 2003 at 15:29 UTC
    And that be the argument for slaping the @ISA assignment in a BEGIN block
    my $foo = Foo->new; print "foo is".($foo->isa( 'Bar' ) ? '' : ' _not_')." a Bar\n"; package Bar; package Foo; BEGIN { @Foo::ISA = qw(Bar); } sub new { bless {},shift } __END__ foo is a Bar

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      Or using the nicer-looking use base. It will complain that the Bar package is empty, so I put a sub in it, but then it works fine.
      my $foo = Foo->new; print "foo is".($foo->isa( 'Bar' ) ? '' : ' _not_')." a Bar\n"; package Bar; sub null {} package Foo; use base Bar; sub new { bless {},shift }
        Hmmm... which version of Perl are you using? I don't need a sub null {} inside Bar to get it to run as expected.

        Slaven Rezic pointed out (on p5p) the use of base.pm as an alternative. I assumed it would always require an external file: apparently it doesn't do that (anymore, anyway, I seem to remember that at one point it did. But I am probably wrong about that).

        What I don't like about base.pm is the extra stuff about fields. Have you ever looked under the hood of base.pm? Yuck!

        Liz

        Update:
        Argh. The reason I didn't get any errors about the empty Bar package, was that I actually had a Bar.pm as an external file hanging around from some previous testing. So yes, you need something in there, not necessarily a sub null {} though, a $VERSION = '0.01' also does the trick. Thanks to Mr. Person for his perseverance proving me wrong in this matter.

Re: Foo is not a Bar, why?
by chromatic (Archbishop) on Dec 18, 2003 at 17:32 UTC

    I'm not sure your moral is fair. Would you conclude that variables are bolted onto Perl 5 after running the following code?

    print $Foo::x; package Foo; $x = "Hello";
      No, but the fact that you have to use package globals to indicate inheritance, does indicate to me that inheritance was added later.

      Now, if Perl had a syntax such as:

      package Foo isa Bar;
      I betcha I wouldn't have had this problem. ;-)

      Liz

        No, but the fact that you have to use package globals to indicate inheritance, does indicate to me that inheritance was added later.

        But... Everything was added later. Have you tried Perl 1.0? Almost everything we use now was bolted on later. And I'm glad it was.

        Also, I'm glad they did this with a package global. Being able to change @ISA later has come in handy more than once for me.

        Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: Foo is not a Bar, why?
by diotalevi (Canon) on Dec 18, 2003 at 16:53 UTC

    And this is why you aren't supposed to futz with @ISA directly. use base 'Bar'; would have done the right thing for you. You've got to deal with execution order when you inline your module code into your script. When you `use` or `require` a module its code is executed at during the `use | require` but when you inline it then you have to wait until the interpreter gets that far down into the script. The ways around that are to manually put your @ISA stuff into something that happens earlier or `use base` which will do the right thing for you automatically.

    Oops! I accidentally wrote INC earlier. It is now fixed to say @ISA.

Re: Foo is not a Bar, why?
by Abigail-II (Bishop) on Dec 18, 2003 at 21:13 UTC
    This is the same "problem" as:
    print "The colour is ", colour (), "\n"; ... my $colour = "red"; sub colour {$colour}
    And that has nothing to do with objects being bolted on.

    Abigail

      The fact that inheirtance is done at all through a package variable is where the bolted-on part comes in. Perl just does too much OO stuff at runtime, which ends up being a very good Perl system but not a great OO system.

      ----
      I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
      -- Schemer

      : () { :|:& };:

      Note: All code is untested, unless otherwise stated

        Would you consider Smalltalk a "not great OO system"? It does even more at runtime.

        Also, if Perl 5 introduced both packages and objects, how could objects be "bolted on"? Packages exist, in part, to make objects possible, without requiring OO coding!

        You will never hear me saying Perl's OO system is anywhere near half decent. But the problem pointed out by liz isn't an OO specific problem - it can happen with non-OO code as well.

        Abigail

Re: Foo is not a Bar, why? (DWIM overload)
by Aristotle (Chancellor) on Dec 25, 2003 at 18:29 UTC

    Variable initialization race conditions are always something to be wary of. I admit I was fooled by your code; this is why when I put packages right into a script rather than into separate module files, I instinctively stick the entire package into a BEGIN { } block and think later.

    The "problem" lies more with the fact that Perl has so many DWIM nooks and crannies that it is easy to make a destructive change instead of transforming to something equivalent if you don't pay attention very carefully.

    Makeshifts last the longest.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://315535]
Approved by Corion
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2024-04-19 02:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found