Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested subroutines and Scoping in Perl

I'm writing Perl for quite some time now and always discovering new things, and I just ran into something interesting that I don't have the explanation to it, nor found it over the web.

sub a {
   sub b {
     print "In B\n";
   }
}
b();

how come I can call b() from outside its scope and it works?

I know its a bad practice to do it, and I dont do it, I use closured and such for these cases, but just saw that.

like image 960
snoofkin Avatar asked Apr 17 '12 13:04

snoofkin


People also ask

What is scoping in Perl?

The scope of a variable is the part of the program where the variable is accessible. A scope is also termed as the visibility of the variables in a program. In Perl, we can declare either Global variables or Private variables. Private variables are also known as lexical variables.

What is subroutine in Perl?

A Perl function or subroutine is a group of statements that together perform a specific task. In every programming language user want to reuse the code. So the user puts the section of code in function or subroutine so that there will be no need to write code again and again.


2 Answers

Subroutines are stored in a global namespace at compile time. In your example b(); is short hand for main::b();. To limit visibility of a function to a scope you need to assign an anonymous subroutines to a variable.

Both named and anonymous subroutines can form closures, but since named subroutines are only compiled once if you nest them they don't behave as many people expect.

use warnings;
sub one {
    my $var = shift;
    sub two {
        print "var: $var\n";
    }
}
one("test");
two();
one("fail");
two();
__END__
output:
Variable "$var" will not stay shared at -e line 5.
var: test
var: test

Nesting named subroutines is allowed in Perl but it's almost certainly a sign that the code is doing someting incorrectly.

like image 98
Ven'Tatsu Avatar answered Sep 19 '22 17:09

Ven'Tatsu


The "official" way to create nested subroutines in perl is to use the local keyword. For example:

sub a {
    local *b = sub {
        return 123;
    };
    return b();  # Works as expected
}

b();  # Error: "Undefined subroutine &main::b called at ..."

The perldoc page perlref has this example:

sub outer {
    my $x = $_[0] + 35;
    local *inner = sub { return $x * 19 };
    return $x + inner();
}

"This has the interesting effect of creating a function local to another function, something not normally supported in Perl."

like image 45
Tero Niemi Avatar answered Sep 20 '22 17:09

Tero Niemi