in reply to Re^2: say statements within 'sub AUTOLOAD'
in thread say statements within 'sub AUTOLOAD'

ianyappy:

One thing you have to understand about the statement  sub name { ... } is that it always executes at compile time if it is not in a string eval (i.e., is in a block  eval or is a nested subroutine definition in another subroutine). So your impression that "AUTOLOAD isn't even being called" is correct. See example below.

>perl -wMstrict -le "{ package Foo; use warnings; use strict; our $AUTOLOAD; sub AUTOLOAD { eval { sub foo { return 'FOO'; } }; sub bar { return 'BAR'; } print qq{AUTOLOADing '$AUTOLOAD'}; no strict 'refs'; *$AUTOLOAD = sub { return uc $AUTOLOAD }; goto &$AUTOLOAD; } } ;; print 'foo? ', exists &Foo::foo; print Foo->foo; print 'bar? ', exists &Foo::bar; print Foo->bar; print 'baz? ', exists &Foo::baz; print Foo->baz; print 'baz? ', exists &Foo::baz; print Foo->baz; " foo? 1 FOO bar? 1 BAR baz? AUTOLOADing 'Foo::baz' FOO::BAZ baz? 1 FOO::BAZ

In this example,  Foo::foo and  Foo::bar already exist at runtime, so  AUTOLOAD is never called for them. The first time  Foo::baz is called,  AUTOLOAD is called and defines the subroutine and also executes the just-defined subroutine. When  Foo::baz is called subsequently, it exists.

Update: To pound the point about nested subroutine definitions even further into the ground, remove the  sub bar { return 'BAR'; } statement from the  AUTOLOAD function in the example above and replace the  eval statement with
    eval { sub foo { sub bar { return 'BAR'; }  return 'FOO'; } };
or the even more pathological
    eval { sub foo { return 'FOO';  sub bar { return 'BAR'; } } };
The results of execution are the same.

Replies are listed 'Best First'.
Re^4: say statements within 'sub AUTOLOAD'
by ianyappy (Initiate) on Dec 26, 2010 at 03:04 UTC

    Ooops, what I Really meant was i did (use strict;use warnings;use 5.010;use Carp;) :) Not used to the lingo.

    Now I understand what you mean by eval strings, I didn't realize the significance (eval q{} vs eval{}) but I do now.

    I tried calling the method dynamically without using references. It seems to work just as fine:

    #!/usr/bin/perl use strict; use 5.010; use warnings; use Carp; { package Foo; our $AUTOLOAD; sub AUTOLOAD { eval { sub foo { sub bar { return 'BAR'; } return 'FOO'; } }; + print qq{AUTOLOADing '$AUTOLOAD'}; my $method = $AUTOLOAD; $method =~ s/.*:://; $method eq 'baz' ? eval q{sub baz{ return uc $AUTOLOAD }} :die + "Invalid method."; goto &$method; } } print 'foo? ', exists &Foo::foo; say Foo->foo; print 'bar? ', exists &Foo::bar; say Foo->bar; print 'baz? ', exists &Foo::baz; say Foo->baz; print 'baz? ', exists &Foo::baz; say Foo->baz; ######OUTPUT##### foo? 1FOO bar? 1BAR baz? AUTOLOADing 'Foo::baz'FOO::BAZ #AUTOLOADING prints once baz? 1FOO::BAZ