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.