Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between calling named anonymous function and regular subroutine

Tags:

perl

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;
}
like image 968
Dima Avatar asked Jun 14 '26 00:06

Dima


1 Answers

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.
like image 190
ikegami Avatar answered Jun 16 '26 21:06

ikegami