What my
does is it makes the variable lexical to the current scope. Normally in perl, variables are global, and changes to them in a scope effect all other scopes. With my, all changes to the variable are local.
There are two very clear differences between the usage of a lexical or a global variable: one is with recursive functions, and the other with closures.
If you would want to calculate something recursively (say, to calculate factorials), if you would use a global variable, each successive call to the function would clobber the previous one, leaving you with a useless function.
Here's an example in practice:
sub Factorial {
$arg = shift; #pull the argument off
return 1 if $first == 0; #stopping condition
return $arg * Factorial($arg-1); #recurse
}
This will always return 0, because as the functions recurse further towards 0, they keep clobbering the $arg
variable, until it finally returns 1. But by the time it makes its way back up the chain to our value, it keeps multiplying by the global value of $arg
, which is zero.
This is immediately solved with the addition of the my
operator, which will make $arg
lexical. This means that each call to the function has its own conception of what $arg
is, allowing our recursive call to succeed.
Closures are another interesting aspect of lexical variables. It's possible to create anonymous subroutines (called lambda
s in python and other languages) in perl by using sub
without a name. A good use for these types of functions is to save some aspect of the current state to be used for later. (I have a heavy background in TeX, and there, closures are constantly used, it's the \edef
primitive).
Closures can be used in memoization, which is saving the results of processing heavy functions in memory. An example would be as follows to create a function which memoizes another function:
sub Memoize {
my $func = shift; #pull function name off the argument stack
my %cache; #prepare to memoize
my $stub = sub { # anonymous function
my $key = shift;
$cache{$key} = $func->($key) unless exists $cache{$key};
#this caches the result if it doesn't exist
return $cache{$key};
};
return $stub;
};
This function decorates an existent one argument recursive function ref (given as \&Factorial
with the functionality of memoization (practically you would want to use the Memoize module for this, but this is just to show the concept of closure). This would break horribly if not for the various lexical variables. The cache would be shared between all decorated functions. The closure here is that the value of our cache is available to any time we call the returned function, even though outside that function we can continue to use a different hash named %cache
.
Both of these examples are basically taken from the book Higher Order Perl, which is excellent. It helps you understand that perl is a serious programming language, not just a way to write administrative scripts.
Of course, the other answer has the practical reason for why to use strict
, but there's a whole 'nother world as to what lexicals are.
If you're wondering, the way to get global variables with use strict
is to precede them either with our
or with main::
.