在Perl中作用域的BLOCK和函数之间的区别

Bel*_*day 6 variables perl scope

伙计们我有点困惑,当我遇到这个时,我正在玩Perl的范围界面:

#! 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!"
Run Code Online (Sandbox Code Playgroud)

但是当我这样做时:

{
   our $x = "nested";
}

print our($x);  # Prints "nested"
print our $x;   # Prints "nested"
print $x;       # Prints "nested"
Run Code Online (Sandbox Code Playgroud)

所以你们可以向我解释为什么那些作品而不是?

Joe*_*ger 6

重申DVK的答案,our只是一个方便的别名工具.您在这些示例中使用的每个变量实际上都已命名$main::x.在任何词法范围内,您可以使用our在同一范围内使用缩写名称为该变量创建别名; 变量不会重置或被移除到外部,只有别名.这与my使得新变量绑定到该词法范围的关键字不同.


DVK*_*DVK 5

  1. 为了解释块示例为何如此工作,让我们看一下"Modern Perl"一书中的our解释,第5章

    我们的范围

    在给定范围内,使用我们的内置函数声明包变量的别名.
    完全限定的名称随处可用,但词法别名仅在其范围内可见.

    这解释了为什么第二个示例的前两个打印工作(我们在print的范围内重新声明),而第三个不打印(作为我们唯一的别名$ x到块的范围内的包变量).请注意,打印$main::x 正常工作 - 它只是作用于块的别名,而不是包变量本身.


  2. 至于功能:

    • print our $x;并且print our($x)"不工作" - 即正确声明该值未初始化 - 因为您从未调用过初始化变量的函数.观察差异:

      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
      
      Run Code Online (Sandbox Code Playgroud)
    • print $x;由于块our的别名(即在本例中是sub的主体),因此无法使用与块相同的原因 - 因此,您必须在主块的范围内重新别名(print our $x例如),或者在sub之外使用完全限定的包global,在这种情况下它将按预期运行:

      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
      
      Run Code Online (Sandbox Code Playgroud)