Context#
Almost every operator in Perl evaluates its operands in a specific context — list, scalar, void, or boolean — and many operators return different things depending on the context they were called in. The same expression can mean different things in different positions:
my @arr = (10, 20, 30);
my @copy = @arr; # list context — three elements
my $len = @arr; # scalar context — 3
print @arr; # list context — "102030"
print "@arr"; # list context inside "" — "10 20 30"
print "" . @arr; # scalar context (concat) — "3"
@arr; # void context — discarded; warns under -w
Context is the single biggest difference between Perl and most other languages, and the single most common source of «why doesn’t this do what I expect» surprises.
The four contexts#
Context | What the operand sees | Imposed by |
|---|---|---|
list | «give me all of your values» |
|
scalar | «give me one value» |
|
void | «throw the result away» | a statement whose value isn’t used |
boolean | «give me a true/false» |
|
Boolean context is technically a special case of scalar context — the operand is asked for one value, then that value is tested for truth. The two are not always the same: a wantarray-aware sub can detect boolean context separately (see below).
Imposing context#
The left side of an assignment imposes context on the right:
my @x = func(); # func() is called in LIST context
my $x = func(); # func() is called in SCALAR context
my ($x, $y) = func(); # func() is called in LIST context
my ($x) = func(); # also LIST — note the parens
my $x = func(); # SCALAR — same chars, very different
The single most-tripped-over case is my $x = func() vs my ($x) = func(). Without parens, the assignment is a scalar; with them, it’s a 1-element list assignment. If func() returns three things in list context and «the count» in scalar context, the difference is between getting 'first-thing' and getting 3.
Operators impose context too. Numeric and string operators impose scalar context on their operands; print imposes list:
my @arr = (1, 2, 3);
my $n = @arr + 0; # scalar context — 3 + 0 = 3
my $s = @arr . ""; # scalar context — "3"
print @arr; # list context — prints "123"
And the boolean tests impose scalar (boolean) context:
if (@arr) { ... } # true if @arr is non-empty
unless (%hash) { ... } # true if %hash is empty
while (<$fh>) { ... } # context is BOOLEAN, but the diamond op is
# special: it reads ONE line and assigns to $_
What an array yields in scalar context#
An array in scalar context yields its length:
my @arr = (1, 2, 3);
my $n = @arr; # 3
A list literal in scalar context yields its last element (the comma operator):
my $x = (1, 2, 3); # 3 — comma operator, last element
my $x = ('a', 'b', 'c'); # 'c'
These look identical and behave differently. The rule is: arrays have a length, list literals don’t. A bare comma-list is the C comma operator and produces its last operand; an array variable in scalar position is asking «how many»:
my @a = ('x', 'y', 'z');
my $count = @a; # 3
my $last_el = $a[-1]; # 'z'
The scalar operator forces scalar context on whatever follows, which is most useful when the expression position is otherwise ambiguous:
print "got " . scalar(@arr) . " items\n"; # "got 3 items"
print "got " . @arr . " items\n"; # same — concat imposes scalar
print "got @arr items\n"; # "got 1 2 3 items" — list inside ""
What a hash yields in scalar context#
A non-empty hash in scalar context returns a true value (the count of keys, since Perl 5.25); an empty hash returns the false value 0. The shape that matters is the truth value:
if (%h) { ... } # true if %h has any pairs
my $n = keys %h; # explicit: count of keys
my $n = %h; # also count of keys (Perl 5.25+); was a debug ratio earlier
For older code targeting pre-5.25 perls you sometimes still see scalar keys %h; on PetaPerl (target perl 5.42) scalar %h returns the key count and is fine.
wantarray — write context-sensitive subs#
A sub can ask «what context was I called in?» with wantarray:
sub items {
return wantarray ? (1, 2, 3) # list context
: defined wantarray ? 3 # scalar context
: do { warn "items() called in void context\n"; () }; # void context
}
my @list = items(); # (1, 2, 3)
my $cnt = items(); # 3
items(); # void — warning fires
The three-way distinction is the only way to detect void from inside a sub. Use it sparingly: most subs return one shape and let the caller worry about context coercion. The places where wantarray earns its keep are:
Functions that legitimately return either «the list» or «the count» — e.g. text-search routines.
Diagnostic helpers that print a warning when their result was discarded.
A sub that returns different meanings (not just different shapes) based on wantarray is a maintenance hazard. Two named functions read better than one polymorphic one.
Pitfall: scalar(@arr) vs @arr in different positions#
my @arr = (1, 2, 3);
# 1. Function arguments — LIST context
some_func(@arr); # passes 1, 2, 3 as three arguments
some_func(scalar @arr); # passes 3 as a single argument
# 2. String concatenation — SCALAR context
"got " . @arr # "got 3"
# 3. Inside double quotes — array interpolation, NOT scalar!
"got @arr" # "got 1 2 3"
# 4. Boolean test — SCALAR (boolean) context
if (@arr) { ... } # true iff @arr non-empty
# 5. Comparison — SCALAR context on both sides
@arr == 3 # 3 == 3 is true
@arr eq "3" # "3" eq "3" is true; this is rarely what you want
The mismatch between case 2 (concat → scalar) and case 3 (inside "" → list) is the single most-asked Perl context question. Inside "", @arr is array interpolation; outside "", the context of the surrounding expression decides.
Pitfall: list-flattening in function arguments#
A function receives @_ as a single flat list of all its arguments — there is no way for the callee to tell where one array ended and the next began:
sub many {
print "got ", scalar @_, " args\n";
}
my @a = (1, 2);
my @b = (3, 4, 5);
many(@a, @b); # 5 args — both arrays flattened
many(\@a, \@b); # 2 args — two array references
many(scalar @a, scalar @b); # 2 args — two integers (the lengths)
This is the reason references exist: to pass a non-flat shape through the list-flattening calling convention. Anything you want to keep its identity inside @_ must arrive as a reference.
Real example: a sub that returns count or list#
sub digits_of {
my ($s) = @_;
return $s =~ /\d/g; # in list context: all digit chars
# in scalar context: TRUE/FALSE (last match)
}
my @digits = digits_of("a1b2c3"); # ('1', '2', '3') — three matches
my $any = digits_of("a1b2c3"); # 1 — boolean
To make digits_of return a count in scalar context, the right-hand side has to coerce explicitly:
sub digits_of {
my ($s) = @_;
my @d = $s =~ /\d/g;
return wantarray ? @d : scalar @d;
}
my @digits = digits_of("a1b2c3"); # ('1', '2', '3')
my $n = digits_of("a1b2c3"); # 3
This is the canonical «return a list or its length» idiom. Note that without the wantarray switch, return @d would still give the count in scalar context (because of the array-in-scalar rule) — but it’s clearer to be explicit.
See also#
Arrays — the array-vs-list-vs-scalar trichotomy expanded.
Hashes —
%hin scalar context.Comma — the operator that builds list literals and yields its last operand in scalar context.
wantarray— the in-sub way to ask.scalar— force scalar context.reverse— context-sensitive: a list of scalars in list context, a single reversed string in scalar context.References — passing a non-flat shape through the flattening list-context arg convention.