ainkov has asked for the wisdom of the Perl Monks concerning the following question:

Hello mighty monks, here is something strange I encountered today:

MyModule.pm :
package MyModule; use Importer; 1;
Importer.pm :
package Importer; sub import { my $caller = caller; print $caller . "\n"; } 1;

and the last piece, test.pl :

use strict; no strict 'refs'; my $symtab = *{'main::MyModule::'}{HASH}; require 'MyModule.pm'; 1;

When I start test.pl, as shown above, the result is:

main::MyModule

so this is the caller. But if you slightly modify it either by removing

my $symtab = *{'main::MyModule::'}{HASH};
or by changing
require 'MyModule.pm';
to
require MyModule;

the result is just (as expected) MyModule.

I tested it on the latest version of perl (5.18.1), as well on version 5.10.1. Results are the same.
Why this inconsistency happens? It caused me a lot of trouble and for me it looks suspicious.
Thanks.

Replies are listed 'Best First'.
Re: Strange side effect on 'caller' function result
by tobyink (Canon) on Oct 11, 2013 at 16:00 UTC

    That's an odd one. I've reduced your example to a single file test case...

    use strict; use warnings FATAL => qw(all); use Test::More tests => 1; BEGIN { package Wah; $INC{'Wah.pm'} = __FILE__; sub import { my $caller = caller; ::is($caller, "Foo"); } } BEGIN { *main::Foo:: } package Foo; use Wah;
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: Strange side effect on 'caller' function result
by kcott (Archbishop) on Oct 11, 2013 at 18:10 UTC

    G'day ainkov,

    Welcome to the monastery.

    I investigated this for a while. I have some findings but, as yet, no definitive answer. I don't have time to continue this now. I'll post what I have: that may help you, or someone else, towards a resolution; if not, I can continue to look into this tomorrow.

    I created MyModule.pm and Importer.pm exactly as you posted them. They remained unchanged throughout all tests. All tests below used modified versions of test.pl.

    I initially looked at the %main::MyModule:: stash (without referencing the $main::MyModule::{HASH} key):

    $ cat test.pl #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; require 'MyModule.pm'; print Dumper \%main::MyModule::; $ test.pl main::MyModule $VAR1 = { 'BEGIN' => *::MyModule::BEGIN };

    So, "main::MyModule", in the output, is not dependent on "my $symtab = *{'main::MyModule::'}{HASH};"; %main::MyModule:: is created with the key $main::MyModule::{BEGIN}. Next I tried the require within an explicit BEGIN block:

    $ cat test.pl #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; BEGIN { require 'MyModule.pm'; } print Dumper \%main::MyModule::; $ test.pl MyModule $VAR1 = { 'BEGIN' => *MyModule::BEGIN };

    Now we get "MyModule" instead of "main::MyModule"; %main::MyModule::, with just the key $main::MyModule::{BEGIN}, is the same. I repeated both of those tests with "require MyModule;". Without a BEGIN block:

    $ cat test.pl #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; require MyModule; print Dumper \%main::MyModule::; $ test.pl MyModule $VAR1 = { 'BEGIN' => *MyModule::BEGIN };

    And with a BEGIN block:

    $ cat test.pl #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; BEGIN { require MyModule; } print Dumper \%main::MyModule::; $ test.pl MyModule $VAR1 = { 'BEGIN' => *MyModule::BEGIN };

    In both of those cases, we have "MyModule" instead of "main::MyModule"; and %main::MyModule::, with just the key $main::MyModule::{BEGIN}, is still present and unchanged. I next looked at "use MyModule;":

    $ cat test.pl #!/usr/bin/env perl use strict; use warnings; use Data::Dumper; use MyModule; print Dumper \%main::MyModule::; $ test.pl MyModule $VAR1 = { 'BEGIN' => *MyModule::BEGIN, 'import' => *MyModule::import };

    Now, %main::MyModule:: has an additional key: $main::MyModule::{import}.

    That's where I'll have to leave it for now.

    -- Ken