See if you can tell what the code below is going to do. Then, run it and see if it does what you think.
use strict; use warnings; # Comment out unless 5.6+ package Bar; use vars qw/ $AUTOLOAD /; sub new { bless {}, shift }; sub AUTOLOAD { print "AUTOLOAD: @_ : $AUTOLOAD\n"; my $self = shift; die "'$self' is not an object\n" unless ref($self); print "Doing some AUTOLOAD'ing magic\n"; } sub DESTROY {} sub frobnitz { my $foo = new Foo ( input => { } ); } package Foo; sub new { bless {}, shift }; package main; my $bar = Bar->new; $bar->frobnitz;

Go ahead ... I'll wait.

Now, cut'n'paste the 4 lines starting with package Foo; and paste them above package Bar; and re-run. See any differences? And, if you want, revert the code to its original, but change

my $foo = new Foo ( input => { } );
to
my $foo = Foo->new( input => { } );

That is why you shouldn't use the Indirect notation. (By the way, this was tested with 5.8.4 on Solaris.) The issue, by the way, is that the indirect notation is fixed at compile-time, not run-time. This can be seen as

my $foo = new Foo ( input => { } );
is parsed (as shown by B::Deparse) as
my $foo = new(Foo('input', {}));

Since the Foo() function (not method) doesn't exist in package Bar, AUTOLOAD is called. Since the author anticipated that AUTOLOAD would only be called as a method, the first parameter is assumed to be the object. Ooops.

Now, some anticipated responses:

Being right, does not endow the right to be rude; politeness costs nothing.
Being unknowing, is not the same as being stupid.
Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Replies are listed 'Best First'.
Re: Why you shouldn't use the Indirect notation with AUTOLOAD
by Anonymous Monk on Feb 28, 2005 at 16:50 UTC
    That is why you shouldn't use the Indirect notation.
    And not because of the reasons pointed out since way back by Perl illuminators like Tom Christiansen and Mark-Jason Dominus, some of those having found its way into the documentation?

    Your AUTOLOAD example is just a special case of the more fundamental problems mentioned in perldoc perlobj - the manual page that recommends:

    The "->" notation suffers from neither of these disturbing ambiguities, so we recommend you use it exclusively.
    Emphasis not mine.

      Yet for some reason, indirect new calls have found their way into the documentation of many, many CPAN modules. I've seen code snippets that mixed direct and indirect new() calls depending on the examples in the docs.

      There seems to be a persistent belief that new is a keyword. I don't know that anyone would every explain it that way, but indirect constructor code looks like people believe that it is a keyword, not a normal class method call.

        I always assumed that it was because of C, C++, Java, PHP, JavaScript/ECMAScript and VB. These languages (and more, I'm sure) all use new as a keyword. With so many languages constructing objects as new Foo it's no wonder why many do it in Perl. I look at it as yet another example of how perl's flexability allows people to program in a way comfortable to them.

        Ted Young

        ($$<<$$=>$$<=>$$<=$$>>$$) always returns 1. :-)
        Yet for some reason, indirect new calls have found their way into the documentation of many, many CPAN modules.
        Indeed, and that's very unfortunate. Let me try to give an explaination (I don't know whether that's the explaination, it's more a theory of mine):

        In the early years of perl5, new Module @args was the recommended way of calling a constructor. It's shorter than Module -> new (@args), and it's what C++ and some other languages use. So, CPAN modules, and also modules coming with perl5, used this syntax, and so did the main documentation.

        It wasn't that after a few years (1997 I think) that people like Tom and Mark-Jason noticed the potential problems, and started warning against its use. The documentation got updates, but there was still quite some code/documentation using the indirect object syntax out there. Which invites people to copy it when they write new syntax. So there has always been a large amount of module on CPAN using the indirect object syntax - and it has enough critical mass to make some new authors use this as well.

        Also, the problems with the indirect object syntax is infrequent enough that many people will never run into problems with indirect objects, even if they use it daily. How venerable you are to get bitten by the indirect object syntax also depends on your way of coding.

        There seems to be a persistent belief that new is a keyword.

        It's not, but sometimes I wonder whether it would have been better if it was.

      That is why you shouldn't use the Indirect notation.
      And not because of the reasons pointed out ... [in] the documentation?

      I didn't read that sentence as excluding any other reasons for avoiding this syntax, but merely adding one reason with emphasis. Perhaps you can take issue with the emphasis he put to his reason, but I think it's a bit too strong to say he is actually excluding the other reasons.

Re: Why you shouldn't use the Indirect notation with AUTOLOAD
by no_slogan (Deacon) on Mar 01, 2005 at 04:01 UTC
    It's really easy to create a situation where you cannot have a correct order. For example, if you create a frobnitz() method in Foo that mirrors the frobnitz method in Bar, plus added a copy of the AUTOLOAD in Foo. What's the correct order to use now?

    Not as big a problem as you seem to think, since you can predeclare both packages before either of the AUTOLOAD methods appears. In this case, Perl is Flexible Enough (tm). I'm not disagreeing with your advice. I'm just sayin'.

    Also, if you put Foo and Bar in their own .pm files, and have have each use the other (*after* its own package statement), things should work out. I have had load order problems with Perl, but never one that was hard to solve.