local#
Save the current value of a package variable and restore it when the enclosing scope exits.
local is the dynamic-scope operator. It does not declare a new
variable — it reaches into an existing package (global) variable,
stashes the current value on a hidden save stack, and arranges for
the original value to be put back when control leaves the current
block, eval, or do FILE. Called subroutines see the
temporary value. For most “I want a variable local to this block”
needs, the right tool is my; reach for local specifically
when the variable must be a package global — the punctuation
variables, filehandles, or entries in the symbol table — and you
want that global to have a different value for the duration of a
block and every subroutine it calls.
Synopsis#
local EXPR
local $var
local $var = EXPR
local (@list) = LIST
local $hash{key}
local $array[i]
local *GLOB
What you get back#
The value of the localized expression (the new value, after any
assignment in the same statement). The save-stack bookkeeping is a
side effect; the return value matters only when local appears
inside a larger expression:
our $x = 2;
foo($x, local $x = $x + 1, $x); # foo() receives (2, 3, 3)
Dynamic scope, not lexical scope#
local and my are different species of scoping:
mycreates a new, lexically scoped variable. Only code textually inside the enclosing block can see it. Called subroutines cannot.localdoes not create anything. It temporarily overrides the value of an existing package variable. Every piece of code — this block and every subroutine it calls, directly or transitively — sees the new value until the scope ends.
That is why local is the right tool for punctuation variables
like $/, $\, $,,
$_, and $@: those are package
globals that the Perl runtime (and anything called from your code)
reads at well-known names. A my shadowing would not affect
them.
sub slurp {
my ($path) = @_;
open my $fh, "<", $path or die "open $path: $!";
local $/; # undef $/ for this sub only
return <$fh>; # read to EOF in one go
}
The local $/ line above is the single most common local idiom
in real code: temporarily undefining the input record separator so
that readline (<$fh>) returns the whole file. When
slurp returns, $/ is restored to whatever it was
before — even if the caller had also changed it.
What you can and cannot localize#
You can localize:
Package scalars, arrays, hashes —
local $Pkg::var,local @Pkg::arr,local %Pkg::hash. Barewordlocal $vartargets the variable in the current package.Already-declared
ourvariables —ourcreates a lexical alias to a package variable, solocalon it localizes the underlying global.Single elements and slices of package arrays/hashes —
local $hash{key},local $array[3],local @hash{qw(a b)},local @array[0..2].Globs —
local *namecreates a fresh symbol-table entry so that$name,@name,%name,&name, and thenamefilehandle are all dynamically reset together.Conditional lvalues —
local ($cond ? $v1 : $v2)when the chosen branch is itself localizable.
You cannot localize:
A
myvariable.myvariables are lexicals living in a pad, not in the symbol table; they have no package name forlocalto save under. Trying it is a compile-time error:Can't localize lexical variable $x.A
statevariable. Same reason.Read-only magic globals.
local $1 = 2fails withModification of a read-only value attempted— the capture variables cannot be assigned to. (The one exception is$_:local $_has, since 5.14, explicitly stripped magic so it can be reused safely in a subroutine.)
Localizing composite-type elements#
local $hash{key} and local $array[i] save the named slot,
not the value that happens to be there. When the scope ends, the
original value is restored to that same slot — even if the element
was deleted or the array was shortened in the meantime. A deleted
hash key springs back; a popped array element reappears, padding
the array with undef if necessary.
our %hash = (a => "is");
{
local $hash{a} = "drill";
delete $hash{a}; # gone for now...
}
print $hash{a}, "\n"; # ...but restored to "is"
Examples#
Basic: give a global a temporary value for one block. Subroutines called from inside the block see the new value.
our $verbose = 0;
sub log_msg { print "[v=$verbose] $_[0]\n" }
{
local $verbose = 1;
log_msg("inside"); # prints "[v=1] inside"
}
log_msg("outside"); # prints "[v=0] outside"
Slurp-a-file idiom with $/:
my $content = do {
open my $fh, "<", $path or die "open $path: $!";
local $/; # list context for <> now reads all
<$fh>;
};
Temporarily trap $@ so an inner eval
does not clobber the caller’s pending error:
sub try_cleanup {
local $@; # caller's $@ preserved
eval { risky_cleanup() };
# even if eval failed, caller's $@ is untouched
}
Python-style print defaults, scoped to one block:
{
local $, = " ";
local $\ = "\n";
print 1, 2, 3; # "1 2 3\n"
}
print 1, 2, 3; # "123" — defaults restored
List form needs parentheses. The parentheses also give the
right-hand side list context — exactly like my:
our (@wid, %get);
local (@wid, %get) = (@defaults, %overrides);
Localize a single hash element — useful for threading overrides through a call without touching unrelated keys:
our %config = (timeout => 30, retries => 3);
{
local $config{timeout} = 5;
do_probe(); # sees timeout => 5
}
# %config back to (timeout => 30, retries => 3)
Glob localization — whole symbol-table entry for LOG is replaced:
{
local *LOG;
open LOG, ">", "/tmp/trace.$$" or die $!;
run_traced(); # sees our private LOG filehandle
}
# original LOG (if any) is back
Edge cases#
Runtime operator, not a declaration.
localexecutes each time control reaches it. Inside a loop it saves and restores on every iteration — measurable overhead. Lift it out of the loop when the intent is “for the whole loop”:{ local $/ = "\n\n"; # once, not per iteration while (<$fh>) { ... } }
Assignment is evaluated before the save. The right-hand side runs in the enclosing dynamic scope, so
local $x = $x + 1reads the old$x, then saves, then assigns the new value.Scope boundary is dynamic, not lexical. The save is undone when the current block exits at runtime, not when the source block ends textually. Exiting via
return,die,last,next, or a non-local goto still triggers the restore.localon amyis a compile-time error. The parser rejectsmy $x; local $x;withCan't localize lexical variable $x. Useour(or a fully qualified name) if you genuinely need dynamic scoping on that name.Tied arrays and hashes do not currently behave the way the POD describes — localizing the whole aggregate is buggy upstream. Localizing individual elements of a tied aggregate is safe. This caveat is inherited from upstream Perl.
Read-only magicals cannot be assigned.
local $1 = "x"dies at runtime. You canlocal $_(magic is stripped since 5.14) but notlocal $1,local $&, etc.Negative array indices in
local $array[-1]are documented as “particularly surprising” upstream; treat the behaviour as unstable and avoid.delete localextendslocalto the removal of an element:delete local $hash{key}deletes the entry for the current block and restores it on exit. It returns the value that was there before localization.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
my— lexical (compile-time, block-scoped) declaration; the right tool when you want a truly private variableour— lexical alias to a package variable; common partner forlocalwhen the global is in another packagestate— persistent lexical; cannot belocalizeddelete— combined withlocal(delete local $h{k}) to scope an element deletion to the current blockeval— commonlocaltarget:local $@around an innerevalprevents it leaking errors to the caller$/— input record separator; canonicallocaltarget for slurp-mode file reads$_— default scalar;local $_strips magic (since 5.14) so a subroutine can reuse it safely$@— lastevalerror;local $@shields the caller from an innereval’s error