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

Hi Monks. Perhaps a silly question, but havent figured it out yet. Lets say my script A.pl uses B.pm. I want to access a variable declared in A.pl from B.pl *without* passing it as a argument in a sub call... Here is some code that may clarify the question... Thanks in advance!.
A.pl
use B; $aValue = 10; my $B = new B; my $something = $B->aSub;
B.pm
package B; sub new { my $class = shift; my $self = bless {}, $class; return $self; } sub aSub { my $self->shift; #here I want to access A.pl's $aValue whitout having it passed as +parameter into the $B->aSub call... } 1;

Replies are listed 'Best First'.
Re: Variable access across packages?
by syphilis (Archbishop) on Nov 14, 2007 at 14:19 UTC
    I think there's a problem with choosing "B" as the name of the pm file. See if this helps:
    ## A.pl use BB; $aValue = 10; BB::aSub();
    And the pm file:
    ## BB.pm package BB; sub aSub { print $main::aValue, "\n"; } 1;
    When I run A.pl, it simply outputs "10".

    Cheers,
    Rob
      Thats's it! is that $main a special variable? Does it refers to the *caller* of the script?

        Yes and no. Yes, $main:: is special. It refers to the package that the "main" script is running in (see perlmod as moritz suggested). However, it is not necessarily the package that called the code that refers to it. For that, look at caller.

        $x = 'main'; Foo::talk(); package Bar; $x = 'Bar'; Foo::talk(); package Foo; sub talk { my ( $package, $filename, $line ) = caller; print "Calling package is '$package'\n"; printf "Caller's \$x is: '%s'\n", ${ $package . '::x' }; } __END__ Calling package is 'main' Caller's $x is: 'main' Calling package is 'Bar' Caller's $x is: 'Bar'
        Yes, the $main::aValue refers back to the calling package, though it's probably better practice to pass the variable instead of using globals. There are always fewer mistakes when you force yourself to be intentional about passing variables.
Re: Variable access across packages?
by moritz (Cardinal) on Nov 14, 2007 at 14:07 UTC
    use strict; use warnings; package B; our $foo = 3; package main; print $B::foo, "\n";

    If you don't want the $B::foo notation, have a look at Exporter

      Qualifying is a good idea, but not necessary with our
      use strict; use warnings; package B; our $foo = 3; package main; print "foo is >$foo<\n"; __END__ foo is >3<

      as opposed to use vars:

      use strict; use warnings; package B; use vars qw($foo); $foo = 3; package main; print "foo is >$foo<\n"; __END__ Global symbol "$foo" requires explicit package name at - line 10. Execution of - aborted due to compilation errors.
      ;-)

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Thanks, moritz, for the reply...
      But I'm looking for something different.
      In your example, main is a package and access a variable declared in package B.
      In my problem, main is not a package but a script and it *uses* B. And I want B to access a variable declared in main without passing it as a argument in a subroutine call.
        every script implicitly runs in the namespace main, so you can just revert the logic and access $main::VariableName if you declared it with our.

        See perlmod for details.

        And I want B to access a variable declared in main
        while this is possible (with global variables) it's generally not a good idea. why give up the modularity gained from using a module if there are other ways to solve it?