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

Re: Our, use vars, and magic, oh my!

by chipmunk (Parson)
on Aug 23, 2001 at 21:20 UTC ( [id://107413]=note: print w/replies, xml ) Need Help??


in reply to Our, use vars, and magic, oh my!

There are basically two kinds of variables in Perl.
  • Package variables live in the symbol table, and are accessible from anywhere in the program. (In some cases the access requires using a package qualifier.)
  • Lexical variables do not live in the symbol table, and are accessible only from within the lexical scope where they are declared.
However, there are three ways to declare a variable (in the latest version of Perl).
  • use vars qw/ $var /; declares $var as a variable in the current package. Within that package, you can write $var to get that variable. From anywhere, you can write $Pkg::var.
  • my $var; declares $var as a variable in the current lexical scope. Within that scope, you can write $var to get that variable. That's the only way you can access it, and the only place in the code you can access it.
  • our $var; declares $var as a variable in the current package, and sets up $var as an alias to that variable within the current lexical scope. Within that scope, you can write $var to get that variable. From anywhere, you can write $Pkg::var.
Of course, this will be much easier to understand with some examples.

 

Here's an example with use vars. Note that, although the use vars is within a block, it takes effect for the whole file. However, after the switch to package main, $var refers to $main::var.

#!perl -l package Pkg; { use vars qw/ $var /; $var = 7; print $var; # 7 } print $var; # 7 package main; print $var; # undef; $main::var has not been set # error with strict print $Pkg::var; # 7

 

Here's an example with my. Note that only within the lexical block can you access the $var that holds the number 7.

#!perl -l package Pkg; { my $var = 7; print $var; # 7 } print $var; # undef; $Pkg::var has not been set # error with strict package main; print $var; # undef; $main::var has not been set # error with strict print $Pkg::var; # undef; $Pkg::var has not been set

 

Here's an example with our. Note the behavior outside the block before the switch to main; $var refers to the $Pkg::var package variable, but without the package qualifier it would be an error with use strict.
#!perl -l package Pkg; { our $var = 7; print $var; # 7 } print $var; # 7 # error with strict package main; print $var; # undef; $main::var has not been set # error with strict print $Pkg::var; # 7

 

Here's another example with our. Note that, after the switch to package main, $var still refers to $Pkg::var, because we're still in the same lexical scope.
#!perl -l package Pkg; our $var = 7; print $var; # 7 package main; print $var; # 7; even though we switched packages, # $var still refers to $Pkg::var # in this lexical scope print $Pkg::var; # 7
So, both use vars and our declare a variable in the current package. The difference between them is in how you can access the variable. With either one, you can always use $Pkg::var from anywhere. With use vars, you can use $var anywhere in the file, as long as you're in the right package. With our and use strict, you can only use $var within the lexical scope, but you can still use $var after switching packages.

Finally, to answer your question about which of three declarations to use at the top of a script. If you're only accessing the variables from that file, you can use my. If you don't switch to a different package later on in the file, use vars and our are equivalent. If you do switch packages, our could result in surprising behavior, as in the last example above.

 

Update: echo pointed out a few places where I had written $variable instead of $var.

Replies are listed 'Best First'.
Re: Re: Our, use vars, and magic, oh my!
by OzzyOsbourne (Chaplain) on Aug 23, 2001 at 22:10 UTC

    An excellent explanation, but if you look at the example that I provided, what is the answer to question 1? The only post that seems to answer the question is dga's. Is my and our the same in my example?

    -OzzyOsbourne

      This is, in many ways, a followup to chipmunk's excellent post, but with a slight twist in that I do not consider our() or 'use vars' as ways of declaring global variables (there is a subtle but important distinction to be made). OzzyOsbourne asks:

      1.Is there any difference between declaring variables at the beginning of scripts with my or our? Won't their scope be the same?

      Yes, there is a difference, and the difference is that No, the scopes of the *variables* will not be the same --- one will be a lexical variable (my) and the other will be a package-global variable (our). I think one major problem people have with my(), our(), and 'use vars' is that we all tend to discuss them as ways of declaring 'variables', and then confusion sets in because the scope of what we declared doesn't always coincide with the scope of the variable which doesn't seem to make sense. Do not think of our() and 'use vars' as ways of declaring *variables* and things become clearer.

      Lexical variables *are* declared and created with the my() declaration. Package variables are never really "declared" at all ... what is really being declared with either 'use vars' or our() is not the variable per se, but "unqualified access" to a package variable under the 'strict' pragma.

      You seem to be looking for an answer that says, "You absolutely should use my..." or "You absolutely should use our..." to declare variables at the top of the script. Well, there really isn't a definite answer like that. It partly depends on how you're using the variables, and partly on personal preference.

      If you are only using the variables from within that file, then you can declare with my. But you can still declare with use vars or our as well. It's really up to you. The script you're asking about should work the same whichever way you declare %TOC.

      If you are accessing the variables from another file, then you have to declare with use vars or our. They are mostly the same when used at the top of the file, but our has the unusual behavior of crossing package boundaries.

      Personally, I still do most of my coding for perl5.005, so I don't use our. I generally use my, except when I'm declaring packing variables or working with mod_perl.

Log In?
Username:
Password:

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

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

    No recent polls found