A few months ago, a certain monk talked me out of using base (and apparently took it to the next level) with a few well placed backhanded comments about what it does and doesn't do. I had been using it religiously since I liked the feel of use base 'Module::Name'; and never much thought about it beyond that.

He pointed out that one of the things it claims to do (load the module if it's not there) frequently doesn't work correctly. In fact, in the places I used it, I had habitually loaded most modules I by hand, without realizing that I was working around a pseudo-bug.

He also pointed out that push @ISA, qw(Module::Name) is probably just as clear. That's arguable I suppose, but I was convinced. I didn't need anything else was doing (since I don't even know what fields are for) and I quit using it.

I mentioned this on an IRC channel and discovered that most people really really like (mostly for readability I gather) and so I got to wondering...

Do you like Why? Do you prefer to @ISA = qw(name)? Why?

(Again, personally, I do not find @ISA to be particularly unreadable (especially when, below it, I usually use other "unreadable" things like $_ and (stat _)[9]). So I just use @ISA.)


Replies are listed 'Best First'.
Re: vs @ISA
by creamygoodness (Curate) on Oct 08, 2007 at 05:07 UTC

    base is fine until you encounter one of its screwy action-at-a-distance behaviors. Then, after you've finally hunted down what the #$@&! is going on, you will curse it.

    Enjoy the fun while it lasts.

    Marvin Humphrey
    Rectangular Research ―

      Based on reading the thread you linked, and testing the code, this action-at-a-distance behavior can be avoided simply by using the module first.

      From what I understand there are three major arguments against

      1. Hidden errors when a module cannot be found.
      2. Manipulation of fields (ala when it's not needed.
      3. Inability to pass a list to used modules.

      Given that there are simple counters:

      • Use the module prior to passing it to use base. This solves both 1 and 3.
      • The fields manipulation is conditional, based on whether or not fields have been manipulated prior. If you don't need fields, won't do anything to them.

      So, given all of that, what you're left with is a decision between:

      use Module; use base qw(Module);


      use Module; our @ISA = qw(Module);

      I can tell you I prefer use base from a readability standpoint alone. It also has the advantage of assigning to @ISA at compile-time, instead of run-time, which can resolve some problems if the modules being used attempt to call class methods immediately. Admittedly, this is extremely rare, however.

      If you are aware of any other outstanding problems with, by all means, share them. Otherwise what this boils down to is a simple style issue.

        You are also forgetting that it sets $VERSION for you if you haven't already done it. I found that incredibly confounding when working with some Inline::C code.

        $Your::Module::VERSION = '-1, set by';

        ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: vs @ISA
by kyle (Abbot) on Oct 08, 2007 at 03:32 UTC

    I find "use base qw( Blah::Blah Yadda::Yadda )" to be a lot more readable than @ISA manipulation. This is probably because for a long time I thought ISA was a bus type, and I still have trouble reading "is a" there, in all caps. That said, it's not as if I spend a long time being confused either way.

    I've used base in my own code quite a bit and never had a problem.

Re: vs @ISA (typos)
by tye (Sage) on Oct 08, 2007 at 14:44 UTC

    For me, the major advantage of was that it originally would catch typos for you. Since use base qw( Food::Barf ); would die if there was no Food/ to load (because the module's name is actually Foo::Bar).

    But Schwern's careless featuritis broke that most important feature and broke it so badly that Schwern basically abandoned the module as unfixable when he finally noticed his mistake.

    I think the breakage is fairly easy to fix so I'm quite disappointed that Schwern not only broke a nice module but also chose to not fix it. Not that I'd go back to using the module any time soon after it was fixed, since there would still be too many broken versions of it in circulation.

    Luckily this is no big loss for me since it only saves one line of typing, the typos can still be caught by basic unit testing, and I hardly ever use inheritance in Perl anyway.

    Update: I have a distinct memory of looking at the source code to when I first started using it and finding something extremely simple. Looking around now I suspect that this is a false memory and may have been broken in some of these ways all along. Mea culpa. It wouldn't be the first time the "obvious design requirement" (to me) was only in my head.

    - tye        

      For me, the major advantage of was that it originally would catch typos for you. Since use base qw( Food::Barf ); would die if there was no Food/ to load (because the module's name is actually Foo::Bar).

      That's interesting. I never knew base() ever did that. When did the functionality change?

      Personally I like the current behaviour more - since I can switch between inline and file-based classes without having to change any code. A definite plus as far as I'm concerned.

        There is little reason for the two features to be mutually exclusive.

        All that is needed is a better choice for when to not require and to not then also ignore if require fails.

        Also note that the behavior that several people have had problems with and that caused me to stop using the module (and that Schwern appeared to abandon trying to fix) is the one that forces people to add require even though they used base. So running into that problem would break your favorite feature.

        So the fixes I would make would prevent your pet feature from breaking.

        Also note that there are several pitfalls to putting multiple related classes into a single file (just a few days ago somebody at PerlMonks had exactly that problem) and as I would fix it would require that parent classes be defined before derived classes, which might catch some problems for some people but might be inconvenient for you.

        - tye        

Re: vs @ISA
by perrin (Chancellor) on Oct 08, 2007 at 03:45 UTC
    I switched to base soon after it came out, because it saved me the trouble of loading the parent module with a separate use() statement, which I sometimes forgot to do. I never use() the module I pass to base and have never had any problems with it.
Re: vs @ISA
by lima1 (Curate) on Oct 08, 2007 at 09:59 UTC

      That's a somewhat different question.

      I was hoping to gather together some of the links to usenet and the cpan mailing list and things. And, I had hoped to get a response from one of the people that posted to those places as I found that stuff pretty hard to find when this came up on IRC.

      I know I've read the stuff all over, but I don't know where it actually is.

      UPDATE: Although, there are some interesting comments under there ... Maybe I duped. :(


Re: vs @ISA
by ysth (Canon) on Oct 09, 2007 at 05:48 UTC
    Do you like Why? Do you prefer to @ISA = qw(name)? Why?
    That should be BEGIN { @ISA = qw(name) }. You can avoid some problems in some cases by making sure your inheritance is set up front and at compile time.

    (And I'd throw in an "our" there, and junk the qw() in favor of quotes.)

A reply falls below the community's threshold of quality. You may see it by logging in.