the following code
#!/usr/bin/env perl
use strict;
use warnings;
my @foo = (0,1,2,3,4);
foreach my $i (@foo) {
sub printer {
my $blah = shift @_;
print "$blah-$i\n";
}
printer("test");
}
does not do what I would expect.
What exactly is happening?
(I would expect it to print out “test-0\ntest-1\ntest-2\ntest-3\ntest-4\n”)
The problem is that the
sub name {...}construct can not be nested like that in aforloop.The reason is because
sub name {...}really meansBEGIN {*name = sub {...}}and begin blocks are executed as soon as they are parsed. So the compilation and variable binding of the subroutine happens at compile time, before the for loop ever gets a chance to run.What you want to do is to create an anonymous subroutine, which will bind its variables at runtime:
which prints
Presumably in your real use case, these closures will be loaded into an array or hash so that they can be accessed later.
You can still use bareword identifiers with closures, but you need to do a little extra work to make sure the names are visible at compile time: