map#
Apply a block or expression to each element of a list and return the flattened results.
map evaluates BLOCK (or EXPR) once per element of LIST, with
$_ aliased to that element, and collects everything each evaluation
returns into a single flat list. Because each evaluation may yield
zero, one, or many values, the output length is independent of the
input length — that flattening is the point of map. In list context
map returns the generated list; in scalar context it returns the
total element count.
Synopsis#
my @out = map { BLOCK } LIST; # block form
my @out = map EXPR, LIST; # expression form
my @out = map { f($_) } grep { ... } sort LIST; # chained
What you get back#
A single flat list built by concatenating the return values of each evaluation, in input order:
Return one value per input → transform (same length out).
Return a list per input → 1-to-N expansion (longer out).
Return the empty list
()→ skip this input (shorter out;map-as-filter idiom).
In scalar context the return value is the count of generated elements, not a reference and not a boolean. Assigning the result to a hash is well-defined: the flat list is consumed as alternating key/value pairs.
my @doubled = map { $_ * 2 } 1 .. 4; # (2, 4, 6, 8)
my @words = map { split /\s+/, $_ } @lines; # 1-to-N
my @kept = map { $_ > 0 ? $_ : () } @nums; # filter
my $count = map { $_ * $_ } @nums; # scalar ctx
Global state#
$_ is aliased to each element of LIST, not copied. Modifying
$_ inside the block modifies the source element. This is
occasionally useful but usually a footgun — reach for a plain
foreach loop when you mean to mutate in place.
my @v = (1, 2, 3);
my @r = map { $_ *= 10; $_ } @v;
# @v is now (10, 20, 30) — the source was mutated
Aliasing to a non-variable (a literal, a function return value, a
hash-slice element that doesn’t exist yet) and then assigning to $_
fails at runtime with Modification of a read-only value. See
$_.
map also localises $_ around the call, so an outer $_ visible to
the caller is restored when map returns.
Examples#
Transform — uppercase every word:
my @upper = map { uc } @words;
1-to-N expansion — split each line on whitespace into its tokens:
my @tokens = map { split /\s+/ } @lines;
Filter idiom — keep only truthy, transformed values:
my @positives = map { $_ > 0 ? $_ : () } @numbers;
Build a hash from a list — each evaluation returns a two-element list:
my %seen = map { $_ => 1 } @keys;
my %idx = map { ($keys[$_] => $_) } 0 .. $#keys;
Composed pipeline — sort, filter, transform. map, grep, and sort
all take a LIST on the right, so they chain right-to-left:
my @top = map { "$_->{name}: $_->{score}" }
sort { $b->{score} <=> $a->{score} }
grep { $_->{score} >= 50 }
@records;
Flatten structure — each input contributes a variable number of outputs:
my @leaves = map { ref($_) eq 'ARRAY' ? @$_ : $_ } @mixed;
Pair with index using List::Util::pairs or an explicit index
variable — map itself does not expose one:
my @numbered = do {
my $i = 0;
map { sprintf "%d. %s", ++$i, $_ } @items;
};
Edge cases#
$_is aliased, not copied. Assigning to$_writes back to the source. If the source element is read-only (a constant, the return value of a function call flattened intoLIST) the assignment raisesModification of a read-only value. Treat$_as input-only unless you specifically want the side effect.mapis not a loop.last,next,redo, and loop labels do not apply tomap. They refer to the enclosing real loop and will behave accordingly — usually not what the author intended. Useforeachwhen you need loop-control flow.Void context is deprecated.
map { ... } LIST;with the result discarded emits aUseless use of map in void contextwarning underuse warnings. When you want the side effects, not the list, write aforeach.BLOCKvsEXPRparser ambiguity.{starts both a block and a hash-reference constructor.map { ... } LISTandmap { ... }, LISTlook identical to the parser at the opening brace; Perl guesses based on what it finds next. A block starting with what looks like a hash key plus=>is especially likely to be guessed wrong:my %h = map { "\L$_" => 1 } @a; # guessed EXPR, wrong my %h = map { +"\L$_" => 1 } @a; # unary + forces BLOCK my %h = map {; "\L$_" => 1 } @a; # leading ; forces BLOCK my %h = map { ($_, 1) } @a; # parens — unambiguous my %h = map { lc($_) => 1 } @a; # function call — unambiguous
To return an anonymous hash per element, force the hash-ref constructor with
+{:my @hashes = map +{ lc($_) => 1 }, @array;
Order is stable.
mapevaluates left-to-right and concatenates results left-to-right. The generated list preserves input order, with each input’s contribution appearing contiguously.Empty
LIST.mapevaluates the block zero times and returns the empty list. The block is not evaluated for its side effects.Nested
map. Innermapsees its own$_; the outer$_is shadowed for the duration of the inner evaluation. Capture the outer value first if both are needed:my @pairs = map { my $outer = $_; map { [$outer, $_] } @inner } @outer;
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
grep— same shape asmap, but keeps elements for which the block is true rather than transforming them; chains naturally withmapandsortsort— orders a list; commonly composed withmapvia the Schwartzian transform (map→sort→map)for/foreach— use when you want iteration for side effects, mutation of the source, or loop-control (last/next/redo)x— list repetition operator; orthogonal tomapbut often used to build theLISTthatmapconsumesList::Util::reduce— fold a list to a single value; use when the result is not a list but an aggregate (sum, max, first match)$_— the element alias inside the block; read-only when the source element is a literal or function return value