I'm experimenting with anonymous functions in Perl, and I began to wonder what the difference between calling these two is:
my $read_file = sub {
my ($filename) = @_;
my @lines;
open my $fh, '<:raw', $filename or die "Can't open file $filename: $!";
while (my $line = <$fh>) {
chomp $line;
push @lines, $line;
}
close $fh;
return @lines;
};
And this:
sub read_file {
my ($filename) = @_;
my @lines;
open my $fh, '<:raw', $filename or die "Can't open file $filename: $!";
while (my $line = <$fh>) {
chomp $line;
push @lines, $line;
}
close $fh;
return @lines;
}
sub foo { ... }
is equivalent to
use Sub::Name qw( subname );
BEGIN { *foo = subname foo => sub { ... }; }
This illustrates the following differences:
sub foo { ... } |
my $foo = sub { ... }; |
|
|---|---|---|
| compiled | Once, at compile-time. | Once, at compile-time |
| sub's name | Named foo. This is returned by caller, and it's found in stack traces such as those from Carp::confess. |
Unnamed, unless subname or similar is used as shown above. Leaving it unnamed could lead to frustrating error messages. |
| variable's scope | The sub is assigned to *foo{CODE}, which is visible to the entire program (with proper qualification). This permits its exportation. If you want to restrict its scope, you can use my sub foo { ... }. |
The sub is assigned to my $foo, which is a lexical variable. It's only visible in the lexical scope in which it is found. Using our $foo or a glob would expand that scope if so desired. |
| assignment's timing | The sub is assigned to *foo{CODE} when the sub is compiled. This is also when external variables are captured. |
The sub is assigned to $foo when the assignment is evaluated. This is also when external variables are captured, so each evaluation of the statement creates a new closure. |
| prototype | Calls honour the sub's prototype. | Calling via a reference ignores the sub's prototype. |
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With