John Doe John Doe - 1 month ago 10
Perl Question

Why subroutine needs to be written after the declaration of variables used in it?

Let's assume we have this code, why it fails with the explicit package name error since the function is called only after the declaration of the

$value
?

use strict;
use warnings;

sub print_value{
print "\n$value";
}

my $value = 2;
print_value();


This fails at compile time with :

Global symbol "$value" requires explicit package name at file.pl line 5.
Execution of file.pl aborted due to compilation errors.


And this code works perfectly fine:

use strict;
use warnings;

my $value = 2;
print_value();

sub print_value{
print "\n$value";
}


Ignore the unutility of this programming style or the deprecated coding style, just focus on the context.

Answer

It's because of scope. That's where in your program your variable is visible. Your $value is a lexical variable because you have declared it with my. That means, it exists inside a certain scope (and all the ones below that). In both of your examples that scope is the entire file (which can also be called the global scope).

Perl looks at your code in two stages. The first is compile time, where it checks the syntax and loads dependencies (like use statements). At this point, it will look for the availability of $value inside the function.

Perl will look in these places, but always just as far as it has compiled yet1:

  • the current scope (that's the function's block { ... })
  • the entire file scope
  • package variables (declared with use vars or our)
  • super-global variables (like $$ or others, but those don't apply here)

It will find none of these, because $value has not been declared yet.

use strict;            # this is the scope for $value
use warnings;          #
                       #
sub print_value{       #  # another, smaller scope
    print "\n$value";  #  # that could have its own $value,
}                      #  # but it does not
                       #
my $value = 2;         # but Perl only learns about it here
print_value();         #

None of this comes because you have strict turned on. Only the fact that you have to declare variables, either with my, or our or by using a fully qualified name is because of use strict.

If you did not have strict and did not declare the variable with my, your program would work. $value would be a package variable in that case.

In your second example you have declared $value before the subroutine, so Perl knows at compile time that there will be a $value available in that scope, so it doesn't complain.

use strict;
use warnings;

my $value = 2;         # lexical declared here
print_value();

sub print_value{
    print "\n$value";  # will be available here
}

However, a better approach would be to pass the variable as an argument to print_value.

use strict;            # this is the scope for $value
use warnings;          #
                       #
sub print_value{       #  # scope for $arg
    my $arg = shift;   #  #
    print "\n$arg";    #  #
}                      #  #
                       #
my $value = 2;         # $value available from here
print_value($value);   #

Now Perl sees that there is a $arg inside of the small scope. It doesn't know its value, but it doesn't have to. And $value is also already declared before using it.

Never use variables from the global scope (the entire file) inside of functions. Always pass them as arguments2.


Here are some relevant links:

1) Perl reads from top to bottom and from left to right
2) unless you want to build a singleton or some other type of closure

Comments