Perl Part I · Module 10 · Subroutines and Arguments
Return Values and Context
In most languages a function's return type is fixed by the function. In Perl it is decided by the caller, at the call site, after the fact — the same return statement hands back one value or many depending on how the result is being used. That is a genuinely useful property and it is also the source of the single most surprising thing in this module, because two return statements that behave identically in one context give different answers in the other. Returning a list of three things and returning an array of three things look alike, read alike, and are interchangeable right up until a caller assigns the result to a single scalar, at which point one of them hands back the last item and the other hands back the number three.
Intermediate16 min readPerlPart ISubroutines
Part I · Module 10 · Chapter 10.6 · Return Values and Context
1. The Caller Decides
use strict;
use warnings;
sub from_literal { return (10, 20, 30) }
sub from_array { my @a = (10, 20, 30); return @a }
my $s_lit = from_literal();
my $s_arr = from_array();
my @l_lit = from_literal();
my @l_arr = from_array();
printf "scalar context, list literal : %s <- the LAST item\n", $s_lit;
printf "scalar context, an array : %s <- the COUNT\n", $s_arr;
printf "list context, list literal : %s\n", join(" ", @l_lit);
printf "list context, an array : %s\n", join(" ", @l_arr);scalar context, list literal : 30 <- the LAST item
scalar context, an array : 3 <- the COUNT
list context, list literal : 10 20 30
list context, an array : 10 20 30The bottom two rows are identical. The top two are not.
Both subroutines return three numbers. Assigned to an array, they are indistinguishable. Assigned to a scalar:
return (10, 20, 30)gives 30 — the last element of the list.return @agives 3 — the number of elements.
Neither is arbitrary. Each follows a rule already established elsewhere in this curriculum, and the rules differ:
| Returned thing | In scalar context | Established in |
|---|---|---|
| a list literal | its last element | Chapter 5.6 §3 |
| an array | its element count | Chapter 5.7 |
| a hash | its key count (Perl 5.26+) | Chapter 6.1 |
| a single scalar | itself | — |
return does not impose a context of its own. It hands the expression to whatever the caller asked for, so the behaviour of return @a is the behaviour of @a, and the behaviour of return (1,2,3) is the behaviour of the comma operator in scalar context. There is nothing subroutine-specific here at all — which is why it is so easy to miss.
The same caller line, two answers
Two returns that look alike, one caller line, different results
The middle column is the same in both rows. That is the point: nothing at the call site distinguishes the two cases, so a caller cannot tell which rule applies without reading the subroutine.
2. What the Caller's Left-Hand Side Does
use strict;
use warnings;
sub f { return (10, 20, 30) }
my $one = f();
my ($first) = f();
my ($a, $b) = f();
printf "my \$one = %s <- scalar context\n", $one;
printf "my (\$first) = %s <- list context, first element\n", $first;
printf "my (\$a,\$b) = %s,%s\n", $a, $b;my $one = 30 <- scalar context
my ($first) = 10 <- list context, first element
my ($a,$b) = 10,20One pair of parentheses changes the answer from 30 to 10.
my $one = f() is scalar context, so the list collapses to its last element. my ($first) = f() is list context — the parentheses make the left side a list, even though it has one element — so f() returns all three and the first is assigned.
This is Chapter 5.6 §4's idiom and it is the standard way to take the first thing a subroutine returns:
my ($worst) = sort { $a <=> $b } @slacks;
my ($first_match) = grep { /^alu/ } @names;Without the parentheses it is scalar context on a sort, which is not merely less useful — measured, it is nothing at all:
with parens: -0.5 without: undefUseless use of sort in scalar context at -e line 3.undef, with a warning that names the problem outright. sort in scalar context is explicitly not defined to return anything useful, so Perl warns rather than inventing an answer — which is more helpful than the array-versus-literal case above, where both answers are perfectly well-defined and simply different. Chapter 5.9 covers sort's contexts.
The two forms differ by one character and never warn, which puts them on the short list of Perl constructs worth reading slowly.
3. What Else Imposes Scalar Context
The left-hand side is only one of several ways a caller asks for one value.
use strict;
use warnings;
sub from_array { my @a = (10, 20, 30); return @a }
printf "interpolated : %s\n", scalar(from_array());
printf "in a condition : %s\n", (from_array() ? "true" : "false");
printf "numeric compare: %s\n", (from_array() == 3 ? "equals 3" : "not 3");
printf "in a list : %s\n", join(" ", from_array(), "end");interpolated : 3
in a condition : true
numeric compare: equals 3
in a list : 10 20 30 end| Position | Context | Here |
|---|---|---|
my $x = f() | scalar | 3 |
scalar(f()) | scalar | 3 |
if (f()) | scalar (boolean) | 3, which is true |
f() == 3 | scalar (numeric) | 3 |
my @x = f() | list | 10 20 30 |
my ($x) = f() | list | 10 |
| an argument in a list | list | 10 20 30 end |
print f() | list | see below |
print gives list context, which catches people:
use strict;
use warnings;
sub from_array { my @a = (10, 20, 30); return @a }
print "print gives list context : ", from_array(), "\n";
print "scalar() forces it : ", scalar(from_array()), "\n";print gives list context : 102030
scalar() forces it : 3print takes a list, so from_array() expanded to three elements — and print joins its arguments with nothing, giving 102030. That is Chapter 5.2's rule about print @array, and it means print f() does not tell you what my $x = f() would give. Debugging a return value with print can therefore show you something other than what the calling code sees.
Use scalar() when you want to see the scalar-context value, and remember that printf "%s" also gives list context to its arguments — it is the format string that then consumes only the first.
4. Writing Returns That Do Not Surprise
5. Returning a Hash
use strict;
use warnings;
sub from_hash { my %x = (a => 1, b => 2); return %x }
my $s = from_hash();
my @l = from_hash();
printf "scalar context : %s <- the key count\n", $s;
printf "list context : %d items (keys and values)\n", scalar(@l);scalar context : 2 <- the key count
list context : 4 items (keys and values)In list context a returned hash arrives as its pairs — four elements for two keys — which is exactly what makes my %copy = get_config(); work, and is the same flattening Chapter 10.2 §1 measured on the way in.
In scalar context it gives the key count on Perl 5.26 and later. Chapter 6.1 §3 measured that older Perls returned a bucket-usage string like 2/8 instead, which is why scalar(keys %h) is the portable way to ask.
Returning a hash is fine; returning two hashes is not. They arrive merged, with no boundary — the same problem as two arrays, and Chapter 10.8 is the fix.
6. Why This Matters in Engineering Work
Report-parsing helpers are exactly where this bites. my $rows = parse_report($path); reads as "get me the rows" and gives a count if parse_report returns an array. The script then treats a number as a list of rows, and the first thing that goes wrong is a dereference error far from the cause.
The refactor hazard is real and silent. Wrapping a returned literal in a named array — a change made for readability — flips the scalar-context value from the last element to a count. Every list-context caller is unaffected, so the test suite stays green.
print showing a different value than the caller sees makes debugging this harder than it should be. print f() is list context; my $x = f() is not. Use scalar() when checking.
And the cure is cheap. Return one shape per subroutine, name list-returning subroutines so the plural is visible, and return a count or a last element explicitly when that is what you mean.
7. Common Mistakes
Assuming a returned list in scalar context gives its count. A list literal gives its last element; only an array gives the count.
Assuming they are the same. return (1,2,3) and return @a differ in scalar context and are identical in list context.
my $x = f() when you wanted the first element. Write my ($x) = f().
Debugging a return value with print. That is list context; use scalar().
A subroutine returning different shapes on different paths. Return one shape — usually a reference.
Relying on the scalar value of a returned list. Return scalar(@rows) or $rows[-1] explicitly.
Wrapping a returned literal in a named array during a refactor. It changes the scalar-context value with no warning.
Returning two hashes or two arrays. They arrive merged. Return references.
8. Exercise
Exercise 1 — the central measurement. Write from_literal and from_array from §1. Assign each to a scalar and to an array, and print all four. Confirm the two list-context rows are identical and the two scalar-context rows are not.
Exercise 2 — explain it. For each scalar-context result, name the rule that produced it and the chapter that established it.
Exercise 3 — one character. Print my $one = f(), my ($first) = f() and my ($a,$b) = f() for a subroutine returning (10,20,30). Record all three.
Exercise 4 — the first-element idiom. Use my ($worst) = sort { $a <=> $b } @slacks; on a four-element list. Then remove the parentheses and record both what $worst becomes and what reaches STDERR.
Exercise 5 — what imposes scalar context. For a subroutine returning a three-element array, record the result in each of: my $x =, scalar(), an if, a numeric ==, my @x =, my ($x) =, and as an argument inside join.
Exercise 6 — print lies. Print the return value of an array-returning subroutine with print f() and then with print scalar(f()). Record both and say which matches my $x = f().
Exercise 7 — the refactor. Write sub cols { return ("a","b","c") } and a caller doing my $x = cols();. Record $x. Then rewrite the subroutine as my @c = ("a","b","c"); return @c; without touching the caller, and record $x again.
Exercise 8 — one shape. Take §4's ambiguous parse and rewrite it to return a hash reference on every path. Write a caller that handles both outcomes, and say why scalar context is now the only context.
9. Summary
- The caller decides what a
returnmeans, at the call site, after the subroutine is written. - In list context a returned list literal and a returned array are identical — measured, both gave
10 20 30. - In scalar context they differ: a list literal gives its last element (30), an array gives its element count (3).
returnimposes no context of its own.return @abehaves exactly as@awould, so the rules are Chapter 5.6's and Chapter 5.7's, not subroutine rules.my $x = f()is scalar context;my ($x) = f()is list context — one pair of parentheses, 30 against 10, no warning.printgives list context, soprint f()showed102030wheremy $x = f()would give3. Usescalar()when debugging a return value.- A returned hash arrives as its pairs in list context and its key count in scalar context on 5.26+.
- Return one shape from every path, name list-returning subroutines for the plural, and return a count or a last element explicitly rather than relying on context.
- Wrapping a returned literal in a named array flips the scalar-context value silently, and every list-context test still passes.
Chapter 10.7 turns the question round: wantarray lets the subroutine find out which context it was called in, and decide what to hand back.
Where this fits
Part of the Perl curriculum.
