# Default variables Two variables hold the implicit operands of Perl. `$_` is the default scalar that countless built-ins read when called without an argument. `@_` is the argument array of every subroutine. Together they account for most of the «where did that value come from?» surprises in Perl code. ## `$_` — the default scalar `$_` is the *topic*: the value being talked about right now. A huge swath of Perl’s built-ins consult it when called with no explicit argument: ```perl for my $line (<$fh>) { chomp; # chomp $line — but $line was aliased to $_ print if /\bERROR\b/; # print $_ if $_ =~ /\bERROR\b/ } ``` The full list of built-ins that default to `$_` includes `chomp`, `chop`, `lc`, `lcfirst`, `length`, `pos`, `print`, `printf`, `quotemeta`, `say`, `split` (default pattern), `study`, `uc`, `ucfirst`, `unlink`, the `m//` and `s///` operators, the `tr///` operator, and the `<>`/`-X` filetest operators. Their detail pages name `$_` as the default; this page is the canonical description. ### Aliasing inside `for` and `while` The `for` (and `foreach`) loop **aliases** `$_` to each element of the list, in turn: ```perl my @items = (1, 2, 3); for (@items) { $_ *= 2; # mutates @items in place } # @items is now (2, 4, 6) ``` Modifying `$_` inside the loop modifies the list element itself. This is identical behaviour to [`map`](../perlfunc/map.md), [`grep`](../perlfunc/grep.md), [`any`](../perlfunc/any.md), [`all`](../perlfunc/all.md) — and `first` and `reduce` from `List::Util`. `while (<$fh>)` does **not** alias — it reads each line into `$_` as a fresh copy. You cannot push back into the file by assigning to `$_` in a `while (<$fh>)` loop. ### Localising `$_` A subroutine that wants its own `$_` without disturbing the caller’s must `local`-ise it: ```perl sub categorise { local $_ = shift; # decouple from caller's $_ return 'small' if /^\d{1,3}$/; return 'medium' if /^\d{4,6}$/; return 'large'; } my @sizes; for ('5', '12345', '999999999') { push @sizes, categorise($_); # caller's $_ stays the loop alias } ``` Without the `local`, calling `categorise()` with `shift` would work — but any `=~`, `/.../`, or `chomp` inside it would silently read or write the loop alias, breaking the caller’s iteration. ### `$_` as an lvalue `$_` is a real scalar variable; you can assign to it, take a reference to it, and pass it as an lvalue: ```perl $_ = 'hello'; chomp; # nothing to chomp; $_ unchanged s/l/L/g; # $_ is now 'heLLo' my $ref = \$_; # \$_ is the alias's address $$ref = 'goodbye'; # mutates whatever $_ is currently bound to ``` Beware that the second `$$ref` will write to **whatever `$_` is right now** — which inside a `for` loop is the current list element. References to `$_` taken outside a loop and used inside one rarely do what the author meant. ### Lexical `$_` `our $_` and `my $_` were experimental features that have been removed. `$_` is always the package-global; use `local $_` for isolation. ## `@_` — subroutine arguments Inside a subroutine, `@_` is the array of arguments passed to that call. Each element is **aliased** to the caller’s expression — `@_` is not a copy: ```perl sub double { $_[0] *= 2; # mutates the caller's variable } my $x = 5; double($x); # $x is now 10 ``` This is why most subs start with `my (...) = @_;` — the unpacking creates copies, after which the routine cannot accidentally mutate caller state: ```perl sub greet { my ($name, $greeting) = @_; # decoupled from caller $greeting //= 'Hello'; return "$greeting, $name!"; } ``` The aliasing is occasionally useful — it is how `chomp(@lines)` mutates every element of the caller’s array — but in everyday code the unpacked-copy idiom is the rule. ### `wantarray` and the calling context A sub that wants to behave differently depending on whether it was called in scalar, list, or void context inspects [`wantarray`](../perlfunc/wantarray.md): ```perl sub items { return wantarray ? (1, 2, 3) : 3; } my @list = items(); # (1, 2, 3) my $cnt = items(); # 3 items(); # void — return value discarded ``` `@_` and `wantarray` are the two pieces of the calling-convention picture. `@_` says *what* was passed; `wantarray` says *what is expected back*. ### `@_` after `shift`, `pop`, `unshift`, `push` Modifying `@_` itself (not its elements) has no aliasing effect on the caller — it’s a normal local array variable. `shift @_` removes the first argument, leaving the rest: ```perl sub method_call { my $self = shift; # standard OO pattern my %args = @_; # rest of args as a hash ... } ``` `shift` with no arguments inside a subroutine defaults to `@_`, which is why you see `my $self = shift;` everywhere. ### `$_ = shift` — wait, what? A common deceptive idiom: ```perl sub trim { $_ = shift; # — set caller's $_ — DO NOT DO THIS s/^\s+//; s/\s+$//; return $_; } ``` That `$_ = shift` writes to the package-global `$_`, which is *the caller’s loop topic* if the caller is inside a `for`. The fix is `local`-isation, as above: ```perl sub trim { local $_ = shift; s/^\s+//; s/\s+$//; return $_; } ``` ## See also - [`map`](../perlfunc/map.md), [`grep`](../perlfunc/grep.md) — the most common consumers of `$_` aliasing. - [`shift`](../perlfunc/shift.md), [`pop`](../perlfunc/pop.md) — default to `@_` inside a subroutine. - [`wantarray`](../perlfunc/wantarray.md) — the companion of `@_` in the calling-convention picture. - [`local`](../perlfunc/local.md) — the safe way to set `$_` inside a sub that the caller might be iterating with. - [Regex binding](../perlop/binding.md) — `=~` is what you use when you don’t want the implicit `$_` target.