# 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 | |-----------------|-----------------------|-------------|---------------| | `$arr[i]` | one element | array | scalar | | `$hash{key}` | one element | hash | scalar | | `@arr[i, j, k]` | many elements (slice) | array | list | | `@hash{k1, k2}` | many elements (slice) | hash | list | | `%arr[i, j, k]` | key/value slice | array | list (k,v…) | | `%hash{k1, k2}` | 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 (`%`): ```perl 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 ``` ```perl 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: ```perl my %selected = %h{ qw(a c) }; # %selected = (a => 1, c => 3) ``` ## Negative indices on arrays Negative array indices count from the end: ```perl $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: ```perl 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: ```perl @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: ```perl @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**: ```perl $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: ```perl 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): ```perl $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“: ```perl $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: ```perl 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](arrow.md). ## See also - [Arrow](arrow.md) — `->[]` and `->{}` for going through a reference; the arrow-elision rule. - [Assignment](assignment.md) — slice assignment; multi-target destructuring. - [`exists`](../perlfunc/exists.md), [`delete`](../perlfunc/delete.md) — perlfunc forms that take a subscript expression. - [`keys`](../perlfunc/keys.md), [`values`](../perlfunc/values.md) — whole-container forms; the slice operators are the partial forms. - [Arrays](../perldata/arrays.md), [Hashes](../perldata/hashes.md) — the data-types pages explain the sigil-vs-result rule that governs which subscript form to use.