closed_over#

Return the lexicals that a subroutine closes over — the variables it references but did not itself declare.

Synopsis#

use PadWalker qw(closed_over);
my $h = closed_over(\&some_sub);
my ($h, $targs) = closed_over(\&some_sub);

What you get back#

In scalar context, a hash reference keyed on sigiled variable names with references to the enclosing variables as values. In list context, that hash reference plus a second hash reference keyed on the sub’s pad slot indices (as numbers) — useful for tools that need to match up pad positions with values.

Only captured lexicals appear; my variables declared inside the sub itself and our variables are both excluded.

Examples#

Classic closure:

my $n = 41;
my $adder = sub { $n + $_[0] };
my $h = closed_over($adder);
${ $h->{'$n'} } = 100;
print $adder->(1);           # 101

List form for serialisers that need pad indices:

my ($names, $slots) = closed_over($sub);
for my $idx (sort { $a <=> $b } keys %$slots) {
    print "slot $idx -> ", ${ $slots->{$idx} }, "\n";
}

Edge cases#

  • A sub that captures nothing returns an empty hash reference.

  • XS subs and subs with no padlist return empty hashes rather than croaking.

  • Passing a bare CV name (without \&) works the same as passing a code reference — the XS layer dereferences either form.

Differences from upstream#

Fully compatible with upstream PadWalker 2.5.

See also#

  • set_closed_over — substitute the captured variables wholesale.

  • peek_sub — full pad, not just the captures.

  • var_name — given one of the returned references, find its name.