Perl Best Practices [Electronic resources]

Damian Conway

نسخه متنی -صفحه : 317/ 72
نمايش فراداده

5.4. Initialization

Initialize any variable you localize .

Many people seem to think that a localized variable keeps its pre-localization value. It doesn't. Whenever a variable is localized, its value is reset to undef[*].

[*] Or, more accurately, the storage associated with the variable's name is temporarily replaced by a new, uninitialized storage.

So this probably won't work as expected:

use YAML;
# Localize the current value...    (No it doesn't!)
local $YAML::Indent;
# Then change it, if necessary...
if (defined $config{indent}) {
$YAML::Indent = $config{indent};
}

Unless the if statement executes, the localized copy of $YAML::Indent will retain its post-localization value of undef.

To correctly localize a package variable but still retain its pre-localization value, you need to write this instead:

use YAML;

# Localize the current value...
local $YAML::Indent = $YAML::Indent;
# Then change it, if necessary...
if (defined $config{indent}) { $YAML::Indent = $config{indent}; }

This version might look odd, redundant, and very possibly wrong, but it's actually both correct and necessary[*]. As with any other assignment, the righthand side of the localized assignment is evaluated first, yielding the original value of $YAML::Indent. Then the variable is localized, which installs a new container inside $YAML::Indent. Finally, the assignmentof the old value to the new containeris performed.

[*] Okay, so it still

looks odd. Two out of three ain't bad.

Of course, you may not have wanted to preserve the former indentation value, in which case you probably needed something like:

Readonly my $DEFAULT_INDENT => 4;

# and later...
use YAML; local $YAML::Indent = $DEFAULT_INDENT;

Even if you specifically did want that variable to be undefined, it's better to say so explicitly:

use YAML; local $YAML::Indent = undef;

That way any readers of the code can immediately see that the lack of definition is intentional, rather than wondering whether it's an oversight.