Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

How to use variables from other package?

by Anonymous Monk
on Apr 27, 2003 at 06:06 UTC ( [id://253450]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Perl monks,

I wrote some variables in a package:
package CNLLog; my $_POST_CONVERSION = "postConversion"; my $_CORRECTIVE_SCRIPTS = "correctiveScripts";
In another package I wrote:
use CNLLog; $temp = $CNLLog::_POST_CONVERSION; When I print "$temp" I get nothing.
Could you, please, tell me what is wrong ?

Thanks.

edited: Sun Apr 27 19:12:59 2003 by jeffa - formatting

Replies are listed 'Best First'.
Re: How to use variables from other package?
by Chmrr (Vicar) on Apr 27, 2003 at 06:15 UTC

    Lexical variables (those created with my) do not show up in the symbol table, and thus can't be accessed via the $Packagename::variable syntax. In this case (assuming perl 5.6.0 or later), you'll want to do:

    package CNLLog; our $_POST_CONVERSION = "postConversion"; our $_CORRECTIVE_SCRIPTS = "correctiveScripts";

    ..and in the other file..

    print $CNLLog::_POST_CONVERSION;

    Older versions of perl will need to use the use vars pragma. See perldoc vars.

    Update: One should also mention the wonderful article Coping with Scoping, by MJD. See also 'our' is not 'my'.

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

Re: How to use variables from other package?
by Ovid (Cardinal) on Apr 27, 2003 at 06:35 UTC

    The classic way to do this is to export those variables via Exporter.

    package Foo; use base 'Exporter'; use vars qw( @ISA @EXPORT_OK $foo ); @EXPORT_OK = qw( $foo ); $foo = 3;

    And then in your code:

    use Foo qw($foo); print $foo;

    Note that the qw() operator is used. Those are strings being quoted, not variables. See perldoc Exporter for more information.

    Cheers,
    Ovid

    New address of my CGI Course.
    Silence is Evil (feel free to copy and distribute widely - note copyright text)

      Wouldn't it be enough to just do the following:

      Package:

      package Foo; use vars qw( $foo ); $foo = 3;

      Script:

      use Foo; print $Foo::foo;

      It works for me. But is there something wrong with this method? Apart from the fact, that I have to explicity call $foo with the package name.

        One problem I've had when doing this is that strict no longer provides protection against a typo in the variable name. At least by using an import you are making the name available unqualified at compile-time so that perl can check it for you.

        use Foo; print $Foo::fooo; # woops!

        One argument for using a fully qualified name is that you prevent a name clash with a variable in the current scope, although I would consider it bad style to reuse a variable name in two scopes, where it is used in both and from both. It would also indicate to me that the variable has perhaps been badly named.

        As usual it depends on the situation, but you need to be aware of the pitfalls of the approach you take. One module which uses package globals to modify its behaviour is Data::Dumper, which has variables such as Purity and Terse. These have quite common names, but you wouldn't want to export them into the current package because they are only used by the Data::Dumper code.

        Data::Dumper on the other hand does have a more 'modern' interface to the same functions by using an object to store the settings which has the advantage of allows different callers to use different options.

        --
        integral, resident of freenode's #perl
        

      The classic way to do this is to export those variables via Exporter.

      Another, easier (tidier) way is to do so using Exporter::Tidy. That way, you get to export the lexical so that in your module you don't have the overhead that package global variables normally have.

      package Foo; use Exporter::Tidy _map => { '$foo' => \my $foo }; $foo = 3;
      And then, in the code that uses the package, unchanged:
      use Foo qw($foo); print $foo;

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: How to use variables from other package?
by Necos (Friar) on Apr 27, 2003 at 10:52 UTC
    I know this is a bit overkill, but, another solution altogether would be to write a function that just returns the value of your my'd variables. Something like this would work (untested):
    package CNLLog; my $_POST_CONVERSION = "postConversion"; my $_CORRECTIVE_SCRIPTS = "correctiveScripts"; sub postConversion_status { return $_POST_CONVERSION; }
    And in your other package:
    use CNLLog; $temp = CNLLog::postConversion_status; print $temp;
    Exporter is a great module, but sometimes people don't want you stepping over their namespaces (functional or otherwise... And I know that you should use  @EXPORT_OK, but not everyone does that). So, using fully-qualified function calls can be very useful.

    Hope that helps some,

    Theodore Charles III
    Network Administrator
    Los Angeles Senior High
    email->secon_kun@hotmail.com
    perl -e "map{print++$_}split//,Mdbnr;"
      I consider this one of the most safest. Mainly because you will get an error message when you make a typo. Further i think it gives the best overview without juggling with main and module variables.

      Q: Why did the Perlmonk cross the road?
      A: He wanted to escape the match.

        Exporting the variables will lead to an error thrown for any typo under strict as well, and it is always thrown at compile time, while that isn't guaranteed for the function.

        Makeshifts last the longest.

Re: How to use variables from other package?
by nite_man (Deacon) on Apr 27, 2003 at 17:25 UTC
    I would like to suggest OO way.
    Package with constants:
    package C; use vars qw( $AUTOLOAD %const_values ); my %const_values = ( CONST_1 => 1, CONST_2 => 23, CONST_3 => 'Test', . . . ); use overload '``' => sub { return $const_values{shift} } ; # All constants can be accessed as by using AUTOLOAD sub AUTOLOAD { no strict 'refs', 'subs'; if ($AUTOLOAD =~ /.*::([A-Z]\w+)$/) { my $const_name = $1; *{$AUTOLOAD} = sub {return $const_values{$const_name}}; return $const_values{$const_name}; } return undef; } 1;
    Usage in my test.pl:
    #!/usr/bin/perl -w use C; print "Const 1:".C->CONST_1."\n"; print "Const 2:".C->CONST_2."\n"; print "Const 3:".C->CONST_3."\n"; __DATA__ Const 1: 1 Const 2: 23 Const 3: Test
    Hope that it will be usefull for you.
          
    --------------------------------
    SV* sv_bless(SV* sv, HV* stash);
    
Re: How to use variables from other package?
by jonadab (Parson) on Apr 28, 2003 at 02:39 UTC

    You shouldn't be using my on variables that another piece of code somewhere else ever might need to access. my is strictly for variables that will never need to be accessed from anywhere else -- loop counters and internal stuff that other code shouldn't mess with.

    You've probably read or heard somewhere from someone an oversimplistic comment to the effect that you should declare all your variables with my, but if so that is fundamentally wrongheaded. You should declare variables with my when you want them to be accessible exclusively from the current code block (i.e., lexically scoped). (Or when you want to create a closure, but closures are beyond the scope of this discussion.) It especially makes no sense to declare all your varibles with my after a package declaration, because the package declaration already accomplishes the thing that is usually the major goal of lexical scoping (i.e., to keep other code from _accidentally_ tromping your variables or having theirs tromped by your code). There are certainly cases where _certain_ variables should be scoped with my inside a package, or even most of them, but if you're doing it to every single varibale without thinking, don't.

    The Coping with Scoping article that chmrr suggested is (mostly) excellent, and you should read it if there's any part of what I said above that you don't fully understand. It neglects to explain why you would _want_ other code to be able to expressly alter your variables, but from your post it appears that you already understand that part. It also does not explain dynamic scope 100% correctly (and in fact is dead wrong on at least one point), but you don't need to understand dynamic scope in order to correctly use lexical and package scope. You _do_ need to understand the differences between package scope and lexical scope, and it explains that very well, so I won't repeat the explanation here. Go read it.


    {my$c;$ x=sub{++$c}}map{$ \.=$_->()}map{my$a=$_->[1]; sub{$a++ }}sort{_($a->[0 ])<=>_( $b->[0])}map{my@x=(& $x( ),$ _) ;\ @x} split //, "rPcr t lhuJnhea eretk.as o";print;sub _{ord(shift)*($=-++$^H)%(42-ord("\r"))};

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-03-29 02:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found