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

I'm trying to set up some constants in a module that will be accessible from other code. The final things will be capitalised and I may experiment with other modules to lock them, but for the moment I'm trying the examples from Simple Module Tutorial, but modified for my needs. And I'm getting frustrated. I have two files:

MyModule.pm

package MyModule; use strict; # Case A use Exporter; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); $VERSION = 1.00; @ISA = qw(Exporter); @EXPORT = (); #@EXPORT_OK = qw(func1 func2); @EXPORT_OK = qw(@rray); # %EXPORT_TAGS = ( DEFAULT => [qw(&func1)], # Both => [qw(&func1 &func2)]); # sub func1 { return reverse @_ } # sub func2 { return map{ uc }@_ } # Case B # use Exporter qw(import); # our $VERSION = 1.00; # our @ISA = qw(Exporter); # our @EXPORT_OK = qw(@rray); # All cases my @rray = (1, 2, 3, 4); 1;

MyScript.pl

use strict; # case 1 # use MyModule; # print scalar(@rray); # case 2 # use MyModule; # print scalar(@MyModule::rray); # case 3 use MyModule qw(@rray); print scalar(@rray);

Case 1 returns Global symbol "@rray" requires explicit package name as one would expect. Cases 2 and 3 both print 0. Case A or B makes no difference.

Where have I blundered, please?

TIA & regards,

John Davies

Replies are listed 'Best First'.
Re: Exporter not behaving as expected
by ikegami (Patriarch) on Mar 27, 2015 at 18:10 UTC

    @rry isn't declared in case 1 because you didn't export anything (@EXPORT = ();).

    Case 2 prints zero since you never assign anything to the array named rray in the MyModule namespace. my creates a lexical variable (i.e. one that's only seen in the lexical scope where it's declared), not a package variable (i.e. one that's located in a package and visible everywhere).

    Just like your script can't see the lexical variable since it's out of scope, Exporter can't see it either. As such, Exporter exports package variables. Case 3 is therefore exports the same variable that you accessed in case 2, a package variable to which you never assigned anything.

    Solutions:

    • @MyModule::rray = (1, 2, 3, 4) instead of my @rray = (1, 2, 3, 4);.
    • use vars qw( @rray ); @rray = (1, 2, 3, 4) instead of my @rray = (1, 2, 3, 4);.
    • our @rray = (1, 2, 3, 4) instead of my @rray = (1, 2, 3, 4);.

      Thanks. I've got confused over the difference between my & our before. I thought I had understood the difference, but obviously I hadn't. Your solution works perfectly, so I clearly have some reading to do.

      Thanks again & regards,

      John Davies

        our creates a lexical variable which is aliased to the package variable of the same name in the package where the our is located.

        our $foo;

        isbehaves the same as

        alias my $foo = $MyModule::foo;

Re: Exporter not behaving as expected
by Anonymous Monk on Mar 27, 2015 at 18:03 UTC

    For @rray to be exported by default, it would need to be in @EXPORT.

      Yes, I understand that. I'm not concerned about whether it's by default or not - case 1 merely demonstrates that I am catching errors when no symbol is found. My problem is that an array that is assigned several elements (I've played around with different numbers of elements to no avail) is reported as having none in both cases 2 and 3.

      Regards,

      John Davies

        Oops, misread the question. Friday afternoon and all that :-)