Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Help needed understanding global variables in Perl

by Anonymous Monk
on Mar 05, 2002 at 08:22 UTC ( [id://149304]=perlquestion: print w/replies, xml ) Need Help??

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

Hi. I'm a newbie Perl programmer (but a relatively experienced programmer in C) and I'm having trouble understanding the use of global variables in Perl. I would appreciate if people could help me.

The problem that I'm having is actually very simple: how exactly do I define (rather than declare) a global variable in Perl? (I know that declaring the variable may be done with use vars.)

I see that even under use strict, I don't have to declare/define global variables in Perl: I just need to fully qualify them and they're already there. Is this correct? If it is, then is there any kind of "super" use strict, which helps me catch typos that my programs may have?

Also, is there any way of defining a variable like C's static (i.e., a global variable with local scope). I see that Perl's our is almost what I want, but the variable declared with our in a function is still accessible outside the function if I use the variable's fully qualified name. I fear that I don't completely understand our.

In fact, I have trouble understanding the difference between our ($i); and use vars qw($i); Can anybody help with the difference? They don't seem different to the eyes of this poor Perl newbie.

Thanks in advance for any comments.

Replies are listed 'Best First'.
Re: Help needed understanding global variables in Perl
by Sinister (Friar) on Mar 05, 2002 at 09:12 UTC
    Mmmm...
    First of all: Global variables are not the best thing man has ever invented. It is better to have your routines talk to each other by what they return, then trough the use of global variables. (loose coupling)

    But, sometimes, we do need globals. In that case, if you have read the perldoc on our (do `perldoc -f our` on your $SHELL) you'll notice, that with our you can create a variable that goes beyond even package scope. In that case you would never want to use our inside a routine, because you would like the routine data to be private to that routine.
    eg:
    #!/perl -wT use strict; sub foo { my $foo = "hello"; } sub bar { our $bar = "world"; } foo(); bar(); print "$foo $bar\n";

    Would actualy print " world", since $foo is routine scope and $bar is lexical scope.
    Defining a global variable would require you to do: my $foo in the main scope of a 'package'.
    eg:
    #!/perl -wT use strict; my $foo = "" our $bar = "" sub foo { $foo = "hello"; } sub bar { $bar = "world"; } foo(); bar(); print "$foo $bar\n";

    This will actualy print "hello world" - which would have worked perfectly if you had choosen to do my $bar = ""; instead of our.

    Now to get back on the difference between our and use vars

    NOTE: The functionality provided by this pragma has been
    superseded by "our" declarations, available in Perl v5.6.0
    or later. See the our entry in the perlfunc manpage.


    These lines come directly from the documentation of vars itself.

    I hope this has answered some of your questions.

    A righthanded-lefthand....
    "Field experience is something you don't get until just after you need it."

      A significant difference between use vars and our is that use vars is global in its effect whereas the effect of our is limited to the same lexical scope as my.

      /J\

      Your first program doesn't work with warnings and strict turned on and I guess that this was what I asked in the original post (I was the original poster): the interpolation of $foo in your print function is illegal, since foo is only valid within the sub foo.

      Also, you say that:

      Defining a global variable would require you to do: my $foo in the main scope of a 'package'.
      I guess that you meant declaring a global variable, right?

      It seems that using my $foo in package main doesn't seem to interfere with $main::foo anyway as can be seen in the following code snippet:

      #!/usr/bin/perl use strict; use warnings; use diagnostics; package main; my $foo = "hello"; $main::foo = "world"; print "$foo $main::foo\n";
      (Isn't it weird? It is terrible to think one knows the language after reading a lot about it, but still fail to understand things which should be simple semantics of the language. I would guess that the my $foo under the package main would manipulate the symbol table such that $foo were equal to $main::foo).

      If $foo and $main::foo were the same variable, then the program would print world world, which it does not.

      Furthermore, if you fully qualify your variables in package main, then you don't need to worry with declaring them with my, nor with our, nor with use vars, as can also be seen in the program above (see that $main::foo is not declared; yet, the compiler doesn't complain about it, even though the program is running under use strict).

        It seems you are completely correct. I was under the distinct assumption that defining a variable in a scope (aka declaring) trough the use of our, lifted that variable out of the scope and accesible for other scopes. This seems only trough when using no strict 'vars' (but that would not be nice).

        <off-topic>
          Does it matter whetter we call 'this' defining or declaring? I know the difference between the two, and if you are a nice perl -wT && strict programmer you define and declare all at once, to prevent warnings.
        </off-topic>

        Your snippet leads to the suspicion that more evil-hack's are possible with perl, then I so far realized.
        I off course tested your snippet, and it works prima!
        However if you would add these lines:
        package not_main; { print $foo; print $main::foo; print "\n"; } package main;
        It would _still_ work fine. This puzzles me. (Why one would define more packages inside one script puzzles me as well)

        As you I was somewhat confinced that I knew the language and the behavior of the interpreter by now. This has once again proofed me wrong, and that is what keeps perl interesting!

        And then, last but not least: thnx 4 ur reply ;-)

        A righthanded-lefthand....
        "Field experience is something you don't get until just after you need it."
Re: Help needed understanding global variables in Perl
by broquaint (Abbot) on Mar 05, 2002 at 10:44 UTC
    > how exactly do I define (rather than declare) a global variable in Perl
    The closest thing to a global variable are either "magical" variables or punctuation variables. Check out this node for more info on globals.

    > is there any kind of "super" use strict, which helps me catch typos that my programs may have?
    One of the reasons for using strict is to encourage the use of lexical variables and to move away from globals, which are can be a large cause of confusion to the unwary.

    > is there any way of defining a variable like C's static (i.e., a global variable with local scope)
    Not really. You can use a global variable in a local scope using the local() function.

    # use strict; $foo = "a string"; sub bar { local $foo; print qq(foo is now localized and empty "$foo"\n); }
    Or you could use a closure to create the imitation of a static variable
    { # creates a new lexical scope my $foo = "add text here - "; sub add_text { my $args = join '', @_; $foo .= $args; return $foo; } } # $foo now only referenced by &add_text
    > In fact, I have trouble understanding the difference between our ($i); and use vars qw($i);
    The difference is that our() declares the variable into the current package and is visible for the rest of the lexical scope (in my opinion this is very icky and kinda anti-DWIM). Whereas use vars qw($x @y %z) just declares it's arguments into the current package, and doesn't mess with the lexical scope.
    HTH

    broquaint

    Update: changed explanation of our() vs use vars qw($x @y %z) per rob_au's note. Also realised why tilly has been knocking our() for so long ;-)
    Update 2: also changed explanation of global variables per shotgunefx's note. /me thinks more research before posting might be an idea ...

      There is no difference between the two really. One is a language construct (our()) and the other is a pragma. They both declare package variables (as opposed to lexical variables, which are declared with my(), and don't touch packages) into the current package.

      There is a difference between the scoping between use vars qw/ $var / and our $var - This is described in perldoc -f our and described by Sinister previously in this thread.

       

      perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

      A clarification on the following point.
      The closest thing to a global variable in perl is a variable that lives in main::'s symbol table. This is because whenever a variable is referred it is always looked for in main::. But this is only a last resort,

      This is not true. If you are not in main:: it will not look in main for a variable unless you use our $var and then it's still only I belive in the current lexical scope.
      # Prints nothing. perl -e '$var = 'value';package FOO; print $var' #prints "value" perl -e 'our $var = 'value';package FOO; print $var' #prints "value" perl -e '$var = 'value';package FOO; print $main::var'


      -Lee

      "To be civilized is to deny one's nature."

      The closest thing to a global variable are either "magical" variables or punctuation variables.

      No. All punctuation variables are global, and some are magical. Not every global is a punctuation variable or magical. $foo is a valid global scalar that goes in foo's stash, just like @foo.

      ++ vs lbh qrpbqrq guvf hfvat n ge va Crey :)
      Nabgure bar vs lbh qvq fb jvgubhg ernqvat n znahny svefg.
      -- vs lbh hfrq OFQ pnrfne ;)
          - Whreq
      

        Are punctuation variables truly global or are they forced to be in main:: when unqualified?

        -Lee

        "To be civilized is to deny one's nature."
Re: Help needed understanding global variables in Perl
by rinceWind (Monsignor) on Mar 05, 2002 at 09:19 UTC
    Dear Anonymous Monk,

    you have a number of questions rolled into your query. My first piece of advice is to read perlsub in the core documentation, if you have not already done so.

    Why do you need global variables? You rarely need them in C. If you are wanting to preserve state information between subroutine calls, you should look at using a class, see perltoot object tutorial, or a closure, see Funkyness with closures....

    Also, if the declaration of the sub is inside a block, it has access to 'my' variables declared in the block before the sub, which will keep their value between calls.

    Hope this helps and I haven't confused you too much

    --rW

      Oh, sure, I understand that global variables are bad in practice (read: "the real world"). But my question was more theoretic, in the sense that I'm just trying to have a solid background on the language and understand its semantics from the viewpoint of a user.

      Unfortunately, I still have not understood completely the use of (user-defined) global variables with Perl.

Re: Help needed understanding global variables in Perl
by steves (Curate) on Mar 05, 2002 at 14:26 UTC

    This is a good discussion because it brought out some subtle differences between our and globals declared without a scoping qualifier (and use vars ...) that I hadn't thought about. I've actually only been using 5.6 for a while now so our is a bit new to me.

    Here's my question: I was looking at our as a way to declare a global package variable and access that variable unqualified from its package while using strict. But if our also implies scoping where regular globals don't, are there other differences? The big question here would relate to global package variables accessed by other packages. I'm thinking of things like $VERSION and @ISA. Is there a difference declaring these with our versus declaring them unqualified with an associated use vars? our scoping rules seem to indicate that declaring these at the top of a file (compilation unit) limits their scope to that compilation unit. If so, what does that mean for variables accessed by other packages, like @ISA?

      I do not claim to have plumbed the depths of our. However, this seems to be the deal: 'our' variables are package variables, just like $main::foo, except that our makes a LEXICALLY scoped declaration that the variable has been legally imported - basically, you can use it's unqualified package name under use strict.

      use strict; package foo; our $y = "This is in package foo"; # $x and $y both package $foo::x = "This is in package foo"; # variables print $foo::x; { #bare block our $x; print $x; #$x = $foo::x } #end of bare block print $x #Give a warning under use strict #because the 'our' declaration #is out of scope package bar; print $foo::y; #prints $y declared with 'our' in package foo print $foo::x; #prints $x declared with package name in foo

      I don't know if that helps any, (or just confused) but there it is - the weirdness (and, I think, good use) of our.

      Cheers,
      Erik

      I'm thinking of things like $VERSION and @ISA.

      These kind of things are fine, you are only declaring them with our for your own convenience within your module - when they are accessed by perl itself or by another module (in the case of $VERSION and ExtUtils::MakeMaker for instance,) they are accessed as if they were fully qualified. Infact h2xs does declare them as our by default :

      our @ISA = qw(Exporter); # .. removed the comments our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( ); our $VERSION = '0.01';

      /J\

Re: Help needed understanding global variables in Perl
by random (Monk) on Mar 05, 2002 at 18:34 UTC

    I may be misreading your post (it is, as other monks have said, quite a few issues rolled into one) but it seems part of your question is how to catch globals that are declared but not defined. Try using -w or "use warnings" for that.

    -Mike-
      Yes, one of my questions is indeed that.

      But what is the standard way of declaring global variables in Perl? With our? With use vars (which now I know that is obsoleted)? With anything else?

      The problem is that even if I don't declare and define anything, I can get rid of warnings just by fully qualifying the variables. In other words, the script below seems to be entirely legal:

      #!/usr/bin/perl use strict; use warnings; use diagnostics; $main::f = 42; print "The value is $main::f\n";

      The problem is that Programming Perl, 2nd ed. (the one that I have) is not very specific about the subject and I've read already quite a bit of the book (chapters 1, 2, 4, 5 and part of 6).

      I don't intent on using global variables, but I feel bad for having trouble not understanding such elementary subjects after reading a fair amount of the documentation.

        Yes, this is legal code. The answer to your question is that there *is* no mechanism in Perl for declaring global variables. The point of use strict is to force you to think about what you're doing when it comes to variables. It will not, however, prevent you from shooting yourself in the foot. Perl is just not that kind of language.

        On the more general issue: tied up with the whole "global/local" thang is the notion of packages. 'Ave yourself a look at perldoc -f package while you're exploring these issues.

        Finally, lemme recommend, as I have many times before, Dominus' "Coping with Scoping" (follow the link to his page and thence to his site) and, less enthusiastically, my own proposed scoping tutorial.

        I mistrust all systematizers and avoid them. The will to a system shows a lack of integrity -- F. Nietzsche

        A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Help needed understanding global variables in Perl
by Anonymous Monk on Mar 13, 2008 at 19:40 UTC
    I have several cgi scripts that use the same config.pl file. My problem is that I had trouble referencing the %config hash. If I move the 'our %CONFIG = ();' to the config.pl file I get errors, but if I declare it in main:: all is OK. Since config.pl doesn't have a package identifier, I was under the impression that it became part of main:: #!/usr/bin/perl -- use strict; our %CONFIG = (); # need to declare the config vars, fails if moved to config.pl require "config.pl" ; # set the config variables require "net.pl"; # common routines for link exhange require "common.pm"; # common routines for all my cgi's

Log In?
Username:
Password:

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

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

    No recent polls found