Control flow

wantarray#

Report the calling context of the currently executing subroutine.

wantarray lets a subroutine ask the runtime how its caller wrote the call: was the result assigned to a list, to a scalar, or thrown away? The answer is one of three distinct values, and a sub can use it to return different shapes of data, or to skip expensive work altogether when the caller asked for nothing.

Synopsis#

wantarray

Takes no arguments and has no parentheses form — it is a keyword, not a function call.

What you get back#

wantarray returns one of exactly three values, corresponding to the three contexts Perl distinguishes:

Return value

Context of the caller

Typical caller syntax

true (1)

list

my @x = f(); (f())[0]

false ("")

scalar

my $x = f(); if (f()) {…}

undef

void

f(); as a statement

The three-way distinction is why the function “should have been named wantlist()”: the boolean-looking return is actually tri-state, and defined wantarray is the right test for “did the caller want anything at all”.

The canonical idiom#

The pattern wantarray exists for is a sub that adapts its return shape to the caller:

sub records {
    my @rows = heavy_query();
    return wantarray ? @rows : "@rows";
}

my @r = records();          # gets the list
my $s = records();          # gets a space-joined string
records();                  # still runs heavy_query — see below

Pair that with an early-out when the caller asked for nothing:

sub records {
    return unless defined wantarray;    # caller wrote `records();`
    my @rows = heavy_query();           # skipped in void context
    return wantarray ? @rows : "@rows";
}

defined wantarray is the void-context guard. wantarray alone is not — it is false in both scalar and void, and an early return on a false wantarray would break every scalar-context caller.

Context is propagated, not re-interpreted#

wantarray reports the context the caller imposed on the sub, not what the sub does internally:

sub ctx { wantarray ? "list" : defined wantarray ? "scalar" : "void" }

my @a = ctx();      # "list"
my $s = ctx();      # "scalar"
ctx();              # "void"
print ctx(), "\n";  # "list"   — print's LIST is list context
scalar ctx();       # "scalar" — scalar() forces scalar context

Note the last two: print imposes list context on its arguments, and scalar explicitly forces scalar context. Neither is about what ctx does with the result.

Calls from void context#

A sub called as a bare statement runs in void context, and wantarray returns undef inside that sub. This does not cascade: a sub called from within a void-context sub sees whatever context its own caller imposed.

sub inner { defined wantarray ? "wanted" : "void" }
sub outer { my $x = inner(); return $x }

outer();            # outer is void; inner is scalar → "wanted"

Each call site establishes its own context independently. wantarray always reports the nearest enclosing sub’s context, not the dynamic chain’s.

Works inside eval too#

wantarray also reports the context of an eval block or eval EXPR, not just named subroutines:

my @x = eval { wantarray ? (1, 2, 3) : "scalar" };  # (1,2,3)
my $x = eval { wantarray ? (1, 2, 3) : "scalar" };  # "scalar"
eval { defined wantarray ? 1 : 0 };                 # void → 0

This is the same mechanism — eval is a call frame in the same sense a sub is.

Where wantarray has no useful answer#

wantarray’s result is unspecified at these places, and code should not rely on any particular value:

  • The top level of a file (outside any sub).

  • Inside a BEGIN, UNITCHECK, CHECK, INIT, or END block.

  • Inside a DESTROY method.

Treat wantarray as meaningful only within an ordinary sub or eval. Anywhere else, design your code so the answer does not matter.

Examples#

A getter that returns the full list to list callers, the count to scalar callers, and does nothing in void context:

sub warnings {
    return unless defined wantarray;
    my @w = collect_warnings();
    return wantarray ? @w : scalar @w;
}

my @all   = warnings();     # every warning
my $count = warnings();     # just the number
warnings();                 # collect_warnings() is not called

A sub that refuses to be called in void context because the return value is the whole point:

sub must_use {
    defined wantarray
        or croak "must_use: return value must be used";
    return compute();
}

A sub that emits one element per call in scalar context and the whole batch in list context — a shape some iterator-style APIs expose:

sub next_batch {
    state @queue;
    @queue = refill() unless @queue;
    return wantarray ? splice(@queue) : shift @queue;
}

Edge cases#

  • No parentheses, no arguments. wantarray() parses but the empty parens are noise; the keyword takes nothing. wantarray $x is a syntax error, not a call with an argument.

  • Not the caller’s context for operators. wantarray reports the call-frame context only. An expression like $sub->() + 1 puts the call in scalar context; wantarray inside $sub sees scalar, as expected. There is no way to ask “was I called inside an arithmetic expression” — only list / scalar / void.

  • return honours the same context. return @list in scalar context yields the last element, not the count — because return itself sees the caller’s context. Use return wantarray ? @list : scalar @list when you want the count for scalar callers.

  • Boolean context is scalar context. if (f()) calls f in scalar context; wantarray returns false there, not undef.

  • List assignment to an empty list is still list context. () = f(); is list context even though the result is discarded. wantarray returns true. This is useful for forcing list context on a sub whose side effects depend on it.

  • wantarray is not available in XS callers the same way. An XSUB inspects context through GIMME_V; a Perl sub called from an XSUB sees the context the XSUB established for the call.

  • Prototypes do not change wantarray. A ($) prototype forces an argument’s context, not the sub’s own call context.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • return — honours the same list/scalar/void context wantarray reports; the two are designed to be used together

  • caller — inspect the call stack itself (package, file, line, and, in its three-arg form, more context details including whether wantarray would return true there)

  • scalar — force scalar context on an expression, which is what makes wantarray return false in the callee

  • eval — establishes a call frame whose context wantarray also reports