Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between a BLOCK and a function in terms of scoping in Perl

Guys I'm a little bit confused, I was playing with scoping in Perl, when i encountered this one:

#! usr/bin/perl
use warnings;
use strict;

sub nested {
   our $x = "nested!";
}

print $x;     # Error "Variable "$x" is not imported at nested line 10."
print our $x; # Doesn't print "nested!"
print our($x) # Doesn't print "nested!"

But when i do this:

{
   our $x = "nested";
}

print our($x);  # Prints "nested"
print our $x;   # Prints "nested"
print $x;       # Prints "nested"

So guys can you explain to me why those works and not?

like image 681
Belmark Caday Avatar asked Jun 13 '13 02:06

Belmark Caday


2 Answers

To restate DVK's answer, our is just a handy aliasing tool. Every variable you use in these examples is actually named $main::x. Within any lexical scope you can use our to make an alias to that variable, with a shortened name, in that same scope; the variable doesn't reset or get removed outside, only the alias. This is unlike the my keyword which makes a new variable bound to that lexical scope.

like image 50
Joel Berger Avatar answered Nov 03 '22 00:11

Joel Berger


  1. To explain why the block example works the way it does, let's look at our explanation from "Modern Perl" book, chapter 5

    Our Scope

    Within given scope, declare an alias to a package variable with the our builtin.
    The fully-qualified name is available everywhere, but the lexical alias is visible only within its scope.

    This explains why the first two prints of your second example work (our is re-declared in print's scope), whereas the third one does not (as our only aliases $x to the package variable within the block's scope). Please note that printing $main::x will work correctly - it's only the alias that is scoped to the block, not the package variable itself.


  2. As far as with the function:

    • print our $x; and print our($x) "don't work" - namely, correctly claim the value is uninitialized - since you never called the function which would initialize the variable. Observe the difference:

      c:\>perl -e "use strict; use warnings; sub x { our $x = 1;} print our $x"
      Use of uninitialized value $x in print at -e line 1.
      
      c:\>perl -e "use strict; use warnings; sub x { our $x = 1;} x(); print our $x"
      1
      
    • print $x; won't work for the same reason as with the block - our only scopes the alias to the block (i.e. in this case body of the sub) therefore you MUST either re-alias it in the main block's scope (as per print our $x example), OR use fully qualified package global outside the sub, in which case it will behave as expected:

      c:\>perl -e "use strict; use warnings;  sub x { our $x = 1;}  print  $main::x"
      Use of uninitialized value $x in print at -e line 1.
      
      c:\>perl -e "sub x { our $x = 1;} x(); print  $main::x"
      1
      
like image 40
DVK Avatar answered Nov 02 '22 23:11

DVK