Subscript and slice operators#
The bracket-and-brace family that picks elements out of arrays and hashes — and the deref-brace family that does the same through a reference.
Form | Selects | Container | Result type |
|---|---|---|---|
| one element | array | scalar |
| one element | hash | scalar |
| many elements (slice) | array | list |
| many elements (slice) | hash | list |
| key/value slice | array | list (k,v…) |
| key/value slice | hash | list (k,v…) |
A few rules cover all twelve combinations.
The sigil signals the result, not the container#
@arr is the array; $arr[3] is one of its elements. The leading sigil tells you what kind of value you are accessing — scalar ($), list of values (@), key/value list (%):
my @arr = (10, 20, 30, 40, 50);
$arr[2] # 30 — scalar (single element)
@arr[1, 3] # (20, 40) — list of values at those indices
%arr[1, 3] # (1 => 20, 3 => 40) — list of (index, value) pairs
my %h = (a => 1, b => 2, c => 3);
$h{a} # 1 — scalar
@h{'a', 'c'} # (1, 3) — list of values
%h{'a', 'c'} # (a => 1, c => 3) — list of (key, value) pairs
The «%-slice» forms (%arr[...], %hash{...}) are a Perl 5.20 addition that returns key/value pairs as a list. They are the right tool when you want a copy of part of a hash:
my %selected = %h{ qw(a c) }; # %selected = (a => 1, c => 3)
Negative indices on arrays#
Negative array indices count from the end:
$arr[-1] # last element
$arr[-2] # second-from-last
@arr[-3..-1] # last three elements as a slice
Out-of-range positive indices read as undef. Out-of-range negative indices (further back than the start) raise a fatal runtime error:
my @a = (1, 2, 3);
$a[10] # undef (with no warning)
$a[-10] # FATAL: Modification of non-creatable array value
# (the error wording reflects how the lookup is implemented)
Slice as lvalue#
Both array and hash slices are valid assignment targets:
@arr[0, 2, 4] = ('A', 'C', 'E'); # set positions 0, 2, 4
@h{qw(a b c)} = (1, 2, 3); # set three hash keys
(@arr[0, 1], @arr[1, 0]) = ... # be careful: aliasing!
You can swap elements via slice assignment without a temporary:
@arr[$i, $j] = @arr[$j, $i]; # swap two array elements
@h{$key1, $key2} = @h{$key2, $key1}; # swap two hash values
Hash key autoquoting#
Inside {} for hash subscripts, bareword identifiers are auto-quoted:
$h{name} # same as $h{'name'}
$h{first_name} # same as $h{'first_name'}
$h{1_2} # FATAL — not a valid bareword identifier
$h{"1_2"} # quote it explicitly
This is one of the most-loved (and most-bug-causing) Perl conveniences. The bareword-or-not decision happens at parse time based on the literal token; constants and computed values do not benefit:
use constant KEY => 'name';
$h{KEY} # WRONG — this is the bareword "KEY", not the constant!
$h{KEY()} # use empty parens to force function-call evaluation
$h{+KEY} # or unary +, the canonical workaround
The +KEY form is the most compact way to say «this is not a bareword, evaluate it as an expression».
Array indices: integer-coerced, no autoquoting#
[] indices are evaluated as expressions and coerced to integers (truncating toward zero):
$arr[1.7] # $arr[1] — 1.7 truncates to 1
$arr["3"] # $arr[3] — string coerces to integer
$arr[$#arr] # last element ($#arr is last valid index)
The $#arr syntax inside subscripts is idiomatic for «last»:
$arr[$#arr] # last
@arr[0..$#arr] # all of @arr (verbose; just write @arr)
@arr[1..$#arr] # all except first
Mixing — multidimensional access#
Perl 5 does not have native multi-dimensional arrays; nested data is built from references:
my @grid = ([1,2,3], [4,5,6], [7,8,9]);
$grid[1][2] # 6 — chained subscripts on AoA
$grid[1]->[2] # same — the arrow is optional between subscripts
$grid[$y][$x]
The arrow-between-subscripts is implied by Perl’s grammar: when two subscripts immediately follow each other on a deref chain, the -> can be omitted. See arrow.
See also#
Arrow —
->[]and->{}for going through a reference; the arrow-elision rule.Assignment — slice assignment; multi-target destructuring.
exists,delete— perlfunc forms that take a subscript expression.keys,values— whole-container forms; the slice operators are the partial forms.Arrays, Hashes — the data-types pages explain the sigil-vs-result rule that governs which subscript form to use.