# 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: ```perl 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“ | `@a = ...`, `(...)`, function args, `print` | | **scalar** | ”give me one value“ | `$s = ...`, `if/while`, `.`, `+`, comparison | | **void** | ”throw the result away“ | a statement whose value isn’t used | | **boolean** | ”give me a true/false“ | `if`, `unless`, `while`, `&&`, \` | 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: ```perl 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: ```perl 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: ```perl 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**: ```perl my @arr = (1, 2, 3); my $n = @arr; # 3 ``` A **list literal** in scalar context yields its **last element** (the comma operator): ```perl 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“: ```perl 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: ```perl 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: ```perl 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`](../perlfunc/wantarray.md): ```perl 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 ```perl 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: ```perl 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 ```perl 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: ```perl 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](arrays.md) — the array-vs-list-vs-scalar trichotomy expanded. - [Hashes](hashes.md) — `%h` in scalar context. - [Comma](../perlop/comma.md) — the operator that builds list literals and yields its last operand in scalar context. - [`wantarray`](../perlfunc/wantarray.md) — the in-sub way to ask. - [`scalar`](../perlfunc/scalar.md) — force scalar context. - [`reverse`](../perlfunc/reverse.md) — context-sensitive: a list of scalars in list context, a single reversed string in scalar context. - [References](references.md) — passing a non-flat shape through the flattening list-context arg convention.