Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Importing variables (not functions) from in-file packages

by puterboy (Scribe)
on Feb 12, 2014 at 15:27 UTC ( [id://1074633]=perlquestion: print w/replies, xml ) Need Help??

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

For various portability reasons, I need to include a couple of custom packages in the same file as my application.

I have no problem wrapping each package in a BEGIN block and accessing methods the usual way. I can also export subroutines using exporter/import. However, I can't seem to export global variables. My code uses the following paradigm:
use strict; use warnings; MyPackage->import; #My main code $globalVar=1; myfunction(); #===================== BEGIN{ package MyPackage; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(globalVar myfunction); our $globalVar; sub myfunction {} #Rest of package code... }
Running, yields the error 'symbol "$globalVar" requires explicit package name'

When I dump the namespace for %main::, I get:
$VAR79 = 'globalVar'; $VAR80 = *::globalVar;
So, $globalVar seems to be in the namespace, I just can't seem to be able to use it (unless of course I explicitly address it using its originating namespace location as $MyPackage::globalVar)

If I put the package in a separate file and include it using 'use MyPackage', I get the same listing in the %main:: namespace as above but I am then able to access the global error directly without error.

Any ideas what is causing $globalVar not to be recognized when the package is in the same file as main?

Replies are listed 'Best First'.
Re: Importing variables (not functions) from in-file packages
by tobyink (Canon) on Feb 12, 2014 at 16:00 UTC

    The beauty of our is that there is no need to export within the same file. It works lexically.

    use strict; use warnings; package MyPackage; # temporarily step into MyPackage our $globalVar; package main; # back to main $globalVar = 42; print $MyPackage::globalVar, "\n";
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
      Ahhh interesting. I didn't know that one could step in & out of a package multiple times. Thanks

        Yup - and you don't even need to do so at the "top level". package statements can appear within blocks. Like...

        package main; use strict; use warnings; { package Person; use Data::Dumper (); # load, but import nothing! sub new { my $class = shift; bless {@_}, $class; } sub dump { my $self = shift; package Data::Dumper; # The following line is executed in Data::Dumper, # so it can see the "Dumper" sub defined there! print Dumper($self); } # We're back to the Person package here because # the closing brace ended the Data::Dumper package printf "Line %d is in package %s\n", __LINE__, __PACKAGE__; } # And now we're back to the main package. printf "Line %d is in package %s\n", __LINE__, __PACKAGE__; my $bob = Person->new(name => 'Robert'); $bob->dump;
        use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: Importing variables (not functions) from in-file packages
by choroba (Cardinal) on Feb 12, 2014 at 15:46 UTC
    The error "... requires explicit package name" is a compile time error. It means Perl was not able to find where the variable was declared when compiling the script. Just put all the packages before the main package and everything will work.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Thanks. I hadn't realized (and perhaps still don't fully understand) the difference between compile time vs. run time errors for variables and functions. But now that I think of it, I suppose this is consistent with the fact that variables need to be declared ahead of usage (if using strict) while function definitions can follow their usage.

      Is there any analogy to the run-time "BEGIN" to tell the compiler to start (or branch elsewhere)?
Re: Importing variables (not functions) from in-file packages
by AnomalousMonk (Archbishop) on Feb 12, 2014 at 16:12 UTC

    Your original code seems to work as long as the scalar  $globalVar is exported using its correct name, i.e., using the  $ sigil.

    c:\@Work\Perl\monks>perl -wMstrict -le "MyPackage->import; print $::globalVar; $::globalVar=1; print $::globalVar; myfunction(); BEGIN{ package MyPackage; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw($globalVar myfunction); our $globalVar = 42; sub myfunction { print 'hi from ', __PACKAGE__; } } " 42 1 hi from MyPackage
      Cool. It does indeed work. But why does strict cause the compiler crap-out on $globalVar but accept $::globalVar. Isn't $globalVar (when not defined as a lexical variable) just a shortcut for the (main) package variable $::globalVar aka $main::globalVar? Or is the "shortcut" only known at runtime...
        Isn't $globalVar (when not defined as a lexical variable) just a shortcut for the (main) package variable $::globalVar aka $main::globalVar?

        It is a 'shortcut' only if you make the lexical declaration
            our $globalVar;
        Then if the first access of the package variable  $globalVar is after the declaration, everybody's happy; otherwise, the variable name must be fully qualified. See our.

        Because that is what you asked it to do with  use strict 'vars';

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1074633]
Approved by hdb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2024-03-29 13:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found