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

I'm trying to figure out how to set a variable in the calling package that use's a package.

That question might not have been entirely clear, so let me provide an example. Consider the following three files:

--- dev.pl #!/usr/bin/perl -w use strict; use lib './'; use MyPackage; --- MyPackage.pm package MyBase; use strict; use Utils; # return true 1; --- Utils.pm package MyPackage; use strict; # export use base 'Exporter'; our @EXPORT = qw{mysub}; # import sub import { # what goes here to set $var in the caller package? # E.g. $MyPackage::var # export symbols MyPackage->export_to_level(1, @_); } # some subroutine sub mysub { # how do I access $var in the caller package? # E.g. $MyPackage::var } # return true 1;
Here's what I want to happen. When MyPackage uses Utils, Utils create a variable in MyPackage which can be accessed as $MyPackage::var. Furthermore, mysub() needs to be able to get to that variable when it's called. Of course, Utils doesn't know the name of the caller until, y'know, it's called, so I can't just hardcode in a package name.

I think I could muck out a solution using a lot of evals, but that seems like it would be very inefficient. Something a little more in keeping with how symbol tables work seems like a better solution.

Replies are listed 'Best First'.
Re: Set a variable in calling package
by AnomalousMonk (Archbishop) on Jan 21, 2018 at 04:40 UTC

    Or is this more like something you had in mind:

    Output:
    c:\@Work\Perl\monks\TerryBerry>perl set_in_importing_script_1.pl 42


    Give a man a fish:  <%-{-{-{-<

Re: Set a variable in calling package
by AnomalousMonk (Archbishop) on Jan 21, 2018 at 04:14 UTC

    I'm not sure I really understand the question. If you're simply talking about accessing a package-global variable  $MyPackage::var from anywhere in the program (which is what being global means), then assign the variable a value with a statement like
        $MyPackage::var = 42;
    located anywhere in the program, then, at a later time (i.e., after it's been assigned a meaningful value), access the variable with a statement like
        do_something_with($MyPackage::var);
    located anywhere in the program.

    I suspect you actually have something a bit more complicated than this in mind.


    Give a man a fish:  <%-{-{-{-<

Re: Set a variable in calling package
by dsheroh (Monsignor) on Jan 22, 2018 at 08:32 UTC
    You're already using Exporter.

    Exporter is capable of exporting variables as well as subs.

    Is there a reason you aren't just exporting your $var, which would make it a member of both namespaces?

    In prog.pl:

    #!/usr/bin/env perl use strict; use warnings; use 5.010; use lib '.'; use MyModule; my_sub; say "Main program: $var";
    In MyModule.pm:
    package MyModule; use strict; use warnings; use 5.010; use base 'Exporter'; our $var; our @EXPORT = qw( my_sub $var ); sub my_sub { $var = 42; say "Set \$var to $var in my_sub"; }
    Result:
    $ ./prog.pl Set $var to 42 in my_sub Main program: 42
Re: Set a variable in calling package
by AnomalousMonk (Archbishop) on Jan 22, 2018 at 00:08 UTC

    Here's another minimal example. It passes a module name and a string to a parent module that then handles everything. Please understand that I do not recommend this code as any kind of example of best practice or even as vaguely kosher.

    Output from set_in_importing_script_2.pl:
    c:\@Work\Perl\monks\TerryBerry>perl set_in_importing_script_2.pl all variables printed from main: var in MyChest: 'Swiss Army knife' var in MyBox: '6-bladed screwdriver' var in MyBag: '[default]'

    Update: Slight wording change in intro to improve clarity (I hope). No code change.


    Give a man a fish:  <%-{-{-{-<

Re: Set a variable in calling package
by Anonymous Monk on Jan 21, 2018 at 06:15 UTC
    Why? Those needs are considered code smell ... so it would be interesting to know why?

      I'm developing a package that gives some cool features to other packages. It's sorta like Moose, it just has a different set of objectives and techniques.

      Yes, I understand that adding a variable to a package is a suspicious thing to do. In this case it makes sense and the programmer using the module would understand that it's happening (if they read the documentation).

        ... the programmer ... would understand ... (if they read the documentation).

        Famous Last Words! :)


        Give a man a fish:  <%-{-{-{-<

Re: Set a variable in calling package
by BillKSmith (Monsignor) on Jan 22, 2018 at 18:44 UTC
    As I understand your question, you want your subroutine to access the copy of a package variable which is in the caller's package, whatever that might be. Wouldn't it be easier to pass the variable as an argument rather than passing the information to do this?
    Bill