K
Koszalek Opalek
Could you elaborate on the subtlety related to scoping demonstrated
by the listing below?
Routine run_test_1 contains a definition of sub filter().
Filter is then passed in a call to add_elem() as a code reference.
run_test_2 uses a different syntax:
my $filter = sub { ...
and then passes variable $filter.
They work identical in the first run. In the second run, however,
the variable @elems accessed by sub filter is not the same as
the variable defined in the body of run_test_1.
Full disclosure: perl emits the following warning:
Variable "@elems" will not stay shared at /tmp/test.pl line 15
#!/usr/bin/perl
use strict;
use warnings;
use Scalar::Util qw/refaddr/;
sub add_elem {
$_[0]->();
}
sub run_test_1 {
my @elems = ();
sub filter {
printf "%d\n", refaddr \@elems;
push @elems, $_[0];
}
add_elem( \&filter, "abc" );
add_elem( \&filter, "abc" );
printf "Total number of elements %d\n", scalar @elems;
};
sub run_test_2 {
my @elems = ();
my $filter = sub {
printf "%d\n", refaddr \@elems;
push @elems, $_[0];
};
add_elem( $filter, "abc" );
add_elem( $filter, "abc" );
printf "Total number of elements %d\n", scalar @elems;
};
print "--- Test 1 ---\n";
run_test_1();
run_test_1();
print "--- Test 2 ---\n";
run_test_2();
run_test_2();
by the listing below?
Routine run_test_1 contains a definition of sub filter().
Filter is then passed in a call to add_elem() as a code reference.
run_test_2 uses a different syntax:
my $filter = sub { ...
and then passes variable $filter.
They work identical in the first run. In the second run, however,
the variable @elems accessed by sub filter is not the same as
the variable defined in the body of run_test_1.
Full disclosure: perl emits the following warning:
Variable "@elems" will not stay shared at /tmp/test.pl line 15
#!/usr/bin/perl
use strict;
use warnings;
use Scalar::Util qw/refaddr/;
sub add_elem {
$_[0]->();
}
sub run_test_1 {
my @elems = ();
sub filter {
printf "%d\n", refaddr \@elems;
push @elems, $_[0];
}
add_elem( \&filter, "abc" );
add_elem( \&filter, "abc" );
printf "Total number of elements %d\n", scalar @elems;
};
sub run_test_2 {
my @elems = ();
my $filter = sub {
printf "%d\n", refaddr \@elems;
push @elems, $_[0];
};
add_elem( $filter, "abc" );
add_elem( $filter, "abc" );
printf "Total number of elements %d\n", scalar @elems;
};
print "--- Test 1 ---\n";
run_test_1();
run_test_1();
print "--- Test 2 ---\n";
run_test_2();
run_test_2();