Perl Learning Six: Variable scope

Source: Internet
Author: User
Tags variable scope vars

Variable scope

(a) package variables

$x = 1

Here, $x is a package variable. There are 2 important things to know about package variables:

1) If there is no other declaration, the variable is the package variable;
2) package variables are always global.

Global means that package variables are always accessible in each program. After you define $x=1, any other part of the program, even subroutines defined in other files, can affect and modify the value of $x. This is no exception; package variables are always global.

Package variables are categorized into families (called packages). The name of each package variable includes 2 parts. These 2 parts are similar to the variable's own name and family name. If you like, you can call the vice President of the United States ' Al ', but for his full name, Al Gore, it's really too short. Similarly, $x has a full name, in the form of $main::x. The main part is the package qualifier, similar to the ' Gore ' part of ' Al Gore '. Al Gore and Al Capone are different people, even though they are called ' al '. Similarly, $Gore:: Al and $capone::al are different variables, $main:: X and $DBI:: X is also a different variable.

Allows you to specify the package part of the variable name, and if you do, Perl will know exactly which variable you are referring to. For brevity, however, a variable's package qualifier is not typically specified.

1. Current Package

If you only say $x,perl assume that you are referring to the variable $x in the current package. What is the current package? Normally it means main, but you can change the current package and write it in the program:

Package mypackage;

Starting with this, the current package is mypackage. The only thing the current package does is that it affects the interpretation of package variables when you do not specify a package name. If the current package is mypackage, then $x actually refers to $mypackage::x. If the current package is main, then $x actually refers to $main::x.

If you are writing a module, assuming that the module name is MyModule, you might place the following line at the top of the module file:

Package mymodule;

From here, all the package variables you use in the module file will be in the package MyModule, and you can be very confident that these variables will not conflict with the variables in other parts of the program. Don't worry about whether you and the DBI author will use the same variable $x, because the variables will be separated, one is $mymodule::x, the other is $dbi::x.

Remember that package variables are always global. Even if you are not in the DBI bag, even if you have never heard of the DBI package, there is nothing to prevent you from reading or writing to $DBI::ERRSTR. You don't have to do any special things. $DBI:: Errstr, like all package variables, is a global variable that can be accessed globally; the only thing you need to do is get it with your full name. It can even be written like this:

Package DBI;
$errstr = ' ha ha tim! ';

This modifies the $dbi::errstr.

2. Additions to package variables

1) If the package name is empty, it is equivalent to main. So for any x, $::x is equivalent to $main::x.

2) Certain variables are always forced in the main package. For example, if you mention%env,perl assume you mean%main::env, even if the current package is not main. If you want to%fred::env, you have to make it clear that even if the current package is Fred. Other special variables include Inc, all of the single punctuation variable names such as $_,$$, @ARGV, and stdin, STDOUT, and stderr.

3) package name, not variable name, can include:. You can name the variable $dbd::oracle::x. This means that the variable x is in the package dbd::oracle, and it has nothing to do with the package dbd. ISAAC Newton has nothing to do with Olivia Newton-john, and NEWTON::ISAAC has nothing to do with Newton::john::olivia. Although they all seem to start with Newton, it's actually a bit deceptive. Newton::john::olivia is located in the Newton::john bag, not in the Newton.

This is everything you need to know about package variables.

Package variables are global, which means that it is dangerous because there is no guarantee that someone will not destroy them behind the scenes. Before Perl 4, all variables were package variables, which was disturbing. So Perl 5 adds new non-global variables.


(ii) Lexical variables

Other types of variables in Perl are called lexical variables or private variables, because they are private. They are sometimes called my variables, because they are always declared with my. You might want to call them local variables, because their effects are confined to a small part of the program. But don't do that because someone else might think you're talking about Perl's local operator. When you want a local variable, think of my, not local.

my $x;

As stated above, a new variable called X is created, which is completely inaccessible to most of the program, most of which is outside the block of code that declares the variable. This block is called the variable scope. If the variable is not declared in any block, its scope begins at the point where it is declared, to the end of the file.

You can also declare and initialize a My variable, so write:

my $x = 119;

You can also declare several variables at the same time:

My ($x, $y, $z, @args) = (5, 23, @_);

The following example shows where a private variable can be useful. Consider this subroutine:

Sub Print_Report {
@employee_list = @_;
foreach $employee (@employee_list) {
$salary = Lookup_salary ($employee);
Print_partial_report ($employee, $salary);
}
}

If lookup_salary happens to also use a variable named $employee, the variable name is the same as the print_report used, and things get worse. The 2 programmers responsible for Print_Report and Lookup_salary must collaborate to ensure that they do not use the same variable name. This is painful. In fact, even in a medium-sized project, this is intolerable.

The workaround: Use the My variable:

Sub Print_Report {
my @employee_list = @_;
foreach my $employee (@employee_list) {
My $salary = Lookup_salary ($employee);
Print_partial_report ($employee, $salary);
}
}

My @employee_list creates a new array variable that is completely inaccessible outside of the Print_Report function. My $employee creates a scalar variable that is completely inaccessible outside the Foreach loop. You don't have to worry about other functions in the program that will break these variables because they don't have the ability; they don't know where these variables are, because the names of variables have different meanings outside the scope of my declaration. My variables are sometimes called lexical variables, because their scopes depend only on the program text itself, not on the execution details, such as what order to execute. By examining the source code only, you can figure out their scope. Whenever you see a variable, look for my declaration in the previous location in the same block of code. If found, you can confirm that the variable is inaccessible outside of the code block. If the My declaration is not found in the inner code block, go to the previous block, and so on, until you find it. If there is no my declaration anywhere, then this variable is a package variable.

The My variable is not a package variable. They are not part of the package and do not have a package qualifier. The current package will not be affected by how the variable is interpreted. Here is an example:

my $x = 17;

Package A;
$x = 12;

Package B;
$x = 20;

# $x is now 20.
# $A:: X and $B:: X is still undefined

At the top of my $x =17 's declaration creates a new lexical variable called X, whose scope persists to the end of the file. The new meaning of $x overrides the default meaning that $x is a package variable for the current package.

Package A changes the current packet, but since $x points to the lexical variable instead of the package variable, $x = 12 does not have any effect on $a::x. Similarly, after package B, $x = 20 modified the lexical variable instead of any packet variable.

At the end of the file, the lexical variable $x value is 20, the package variable $main::x, $A:: X, and $b::x are still undefined. If they are to be used, they must still be accessed by their full name.

It must be remembered that:

A package variable is a global variable.
For private variables, the My declaration must be used.

1. Local and my

Almost everyone knows that there is a local function, which has some effect on native variables. What is it, and does it matter to me? The answer is simple and strange:

My creates a local variable, but locals do not.

First, what the local $x actually do is that it stores the current value of the package variable $x in a safe place, replaces it with a new value, and uses undef instead if no new value is specified. When control leaves the current block, it also restores the old value of $x. It affects the package variable, which gets the local value. But the package variable is always global, and the local declaration of the package variable is no exception. To show the difference, take a look at this:

$lo = ' global ';
$m = ' global ';
A ();

Sub A {
Local $lo = ' AAA ';
My $m = ' AAA ';
B ();
}

Sub B {
Print "B", ($lo eq ' AAA '? Can ': ' cannot '),
"See the value of Lo set by a.\n";

Print "B", ($m eq ' AAA '? Can ': ' cannot '),
"See the value of M set by a.\n";
}

The result is printed:

B can see the value of Lo set by A.
B cannot see the value of M set by A.

What happened? The local declaration in a function gives the package variable $lo a new temporary value of AAA. The old value global is stored until a returns, but before that, a invokes B. b There is no problem accessing the contents of $lo, because $lo is a package variable, and the package variable is always globally visible, so it can see the AAA value set by a.

In contrast, my declaration creates a new lexical scope variable called $x, which is only visible in the a function. Outside a, the $m retains its old meaning: it points to the package variable $m; its value is still global. This is the variable that B sees. It will not see the AAA value, because that variable is a lexical variable that exists only in a.

What are the benefits of 2.local?

It is not very useful because local variables are not actually created locally. In the above example, if B happens to modify the value of $lo, the value of a setting is overwritten. We really don't want it to happen. We want each function to have its own variables, which are not touched by other functions. That's what my can do.

Why is there a local? Answer 90% is for historical reasons. Earlier versions of Perl had only global variables. Local is very easy to execute, and it is added to PERL4 as a partial solution to local variable problems. Later, more work was done in Perl5, and the real local variables were added to the language. Unlike local, the new native variable is declared with the word my. I was chosen because it implied privacy, and because it was very short, short words might encourage you to use it instead of local. My also runs faster than local.

When to use my, and when to use local?

The answer is simple: Always use my, never use local.

Other features of 3.my variables

Each time the control arrives at my declaration, Perl creates a new, initial variable. For example, the following code prints X=1 50 times:

For (1:50) {
my $x;
$x + +;
print "x= $x \ n";
}

Each time you traverse a loop, you get a new $x whose value is initialized to undef.

If the declaration is outside the loop, the control passes through it only once, so there is only one variable:

{my $x;
For (1:50) {
$x + +;
print "x= $x \ n";
}
}

This will print X=1, x=2, x=3, ... x=50.

You can use this to play a game. Suppose you have a function that remembers a value from one call to the next. For example, consider a random number generator. A typical random number generator (like the RAND function in Perl) has a seed in it. The seed is a number. When a random number generator is requested to obtain a random number, the function performs certain operations based on the seed and returns the result. It also stores the result and takes it as a seed for the next function call.

The following is a typical code:

$seed = 1;
Sub My_rand {
$seed = Int (($seed * 1103515245 + 12345)/65536)% 32768;
return $seed;
}

Typical output:

16838
14666
10953
11665
7451
26316
27974
27550

There is a problem here, because $seed is a global variable, which means we have to worry about someone who might inadvertently modify it. Or someone else intentionally destroys it, which affects the results of the program. If the function is used in a gambling program and someone else destroys its random number generator, what do you think will happen?

But we cannot declare $seed as my variable in the function:

Sub My_rand {
My $seed;
$seed = Int (($seed * 1103515245 + 12345)/65536)% 32768;
return $seed;
}

If you do this, the $seed will be initialized to undef each time you call My_rand. What we actually need is that each time My_rand is called, the $seed retains its value.

Here's how to fix it:

{My $seed = 1;
Sub My_rand {
$seed = Int (($seed * 1103515245 + 12345)/65536)% 32768;
return $seed;
}
}

Declaration is outside the function, so it executes only once at the time of the program's compilation, not every time the function is called. But it's a my variable, and it's in the code block, so it's only visible to the code in the block. My_rand is the only other thing in the block, so $seed can only be accessed by the My_rand function.

4. Additions to my variables

1) You cannot use my declaration for a variable named by punctuation, such as _, @_, or $$. You cannot reference a variable in the background. Use my declaration. My author thinks it's going to mess things up.

2) Obviously, cannot declare my $DBI:: Errstr, because there is a conflict: it thinks that the package variable $dbi::errstr is a lexical variable. But it can be stated that the local $DBI:: errstr; It stores the current value of the local $DBI:: Errstr and restores it at the end of the code block.

3) in Perl 5.004 and later, you can write this:

foreach my $i (@list) {

It restricts $i within the loop range. Similar to the

For (my $i =0; $i <100; $i + +) {

Limit the $i in the For loop.


(c) Variable declaration

If you are writing a function and you want it to have a private variable, you must use my to declare the variable. If you forget, what will happen?

Sub function {
$x = 42; # Oops, should has been my $x = 42.
}

In this case, your function modifies the global package variable $x. If you're going to use that package variable somewhere else, that's a disaster for the program.

Recent versions of Perl have protection options for this, and you can activate it. If placed:

Use strict ' vars ';

At the top of the program, Perl will require that package variables have explicit package qualifiers. $x = 42 in $x No such qualifier, so the program will not even compile; instead, the compiler will break abnormally and output the following error message:

Global symbol "$x" requires explicit package name at ...

If you want $x to be a private my variable, you can go back and add my. If you really want to use global package variables, you can change it back to:

$main:: x = 42;

or other corresponding packages.

Use strict also has additional detection options, see Perldoc Strict for more details.

Now suppose you're writing the Algorithms::knuthbendix module, you want to use strict VARs protection mode, but if you need to type $algorithms::knuthbendix::error over and over again, you'll be bored.

You can tell strict vars to generate an exception:

Package Algorithms::knuthbendix;
Use VARs ' $Error ';

This avoids the strict vars failure caused by the packet variable $algorithms::knuthbendix::error when you use the short name $error.

You can also close strict vars in a block of code, as in the following notation:

{No strict ' vars ';

# Strict VARs is off for the rest of the block.

}


(iv) Summary

Package variables are always global. They have a name and a package qualifier. You can omit the package qualifier so that Perl uses the default package, which is set by the package declaration. For private variables, please use my. Do not use local, it is obsolete.

Avoid using global variables because it is difficult to ensure that 2 parts of the program do not use the other variable incorrectly.

To avoid accidental use of global variables, use strict ' VARs ' in your program. It checks and ensures that all variables are declared private, either explicitly using the package qualifier, or explicitly using the use VARs.


(v) Supplement to ' our '

Perl 5.6.0 introduced a new our (...) Statement. Its syntax is the same as my (), which is a substitute for use VARs.

If we do not delve into the details, our () is similar to use vars; its only effect is to declare variables so that they are exempt from strict ' vars ' checks. However, compared to use VARs, it may have 2 advantages: The syntax is not so weird, the effect is lexical scope. That is, it allows the stict check to fail only within the current block:

Use strict ' vars ';
{
Our ($x);
$x = 1; # using global variables here $x no problem.
}
$x = 2; # using $x here usually causes a compile-time error

So when using the use VARs ' $x ' declaration, the global variable $x can be used everywhere. Our ($x) only allows to declare global variable $x in certain blocks of the program, which can cause errors if accidentally used elsewhere.

Perl Learning Six: Variable scope

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.