Re: Re: Re: Our, use vars, and magic, oh my!by danger (Priest)
|on Aug 24, 2001 at 02:25 UTC||Need Help??|
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.
So, can there be any *effective* difference between declaring a variable with our() or my() at the top of a single, single self contained script? Well, although it certainly isn't good programming style to reuse the same variable names, one difference is that you can never fully mask out a package variable:
Inside the inner block a new lexical $foo is created completely masking out access to the outer lexical $foo (for the remainder of the inner block). A new lexical $bar is also created but only masks *unqualified* access to the package variable $bar, the package $bar is still (is always) accessible via its package name. But that is a contrived example.
Is it better to use my() or our() in single scripts? That is a matter of style and opinion. My rule is to only use package variables when a package variable is necessary. Thus the question isn't "should I use my() or our()?" ... that answer is dictated by whether I need a package variable or not, and then, if I *do* need a package variable, the question really is :should I use our() or 'use vars'?". I guess that depends, but sometimes our() variables won't cut it because their unqualified access is lexically scoped rather than package scoped. For example, if you use the Getopt::Declare module and wish to include a variable within an action-block the docs state that:
Actions are executed (as `do' blocks) in the package in which the Getopt::Declare object containing them was created. Hence they have access to all variables and functions in that scope. (ed. emphasis added)
This is accomplished inside the Getopt::Declare module by taking the action block (as a string), wrapping it in a do block with the caller's package declaration added and eval()'ing it. This means that if the action uses unqualified access to a package global it must be declared with 'use vars' and not our() because the unqualified access of our() is lexically scoped and won't be in effect inside Getopt::Declare's evaluation of the code. For a concrete example:
The above (using our()) will generate an error, but if you use the commented out 'use vars' declaration instead, it will work fine. (aside note: the '-greet' above is followed by a hard tab, not spaces).
My first hard and fast rule is that there are no hard and fast rules. My second hard and fast rule (subject to qualification via the first rule) is to always use lexical variables except when a package variable is required and then 'use vars' is generally still my first choice. In the few instances where I want a package variable, I do not see that our() gives me any additional benefits over 'use vars', and occassionally (as in the Getopt::Declare situation) our() doesn't satisfy the access needs.