Perl中的包变量不在“范围”中?

时间:2014-03-05 14:47:16

标签: perl perlvar

我正在看这个question,当我在玩耍时,我遇到了这个:

#! /usr/bin/env perl
#
# use warnings;
use strict;
use feature qw(say);

{
    our $foo = "bar";
    say "Foo = $foo";
}

say "Foo = $foo";  # This is line #12

是的,我确实关闭了use warnings; ...

当我跑步时,我得到:

Variable "$foo" is not imported at ./test.pl line 12.
Global symbol "$foo" requires explicit package name at ./test.pl line 12.
Execution of ./test.pl aborted due to compilation errors.

嗯...我得到相同的“变量”$ foo“未导入./test.pl第12行。”如果我已完成my $foo = "bar";错误。当我使用my时,我会理解这一点,因为一旦我们离开块,就没有变量$foo。但是,our变量被认为是包范围。我可以理解$foo当时可能没有值,但是这个?

此外,“变量”$ foo“未在./test.pl第12行导入。”是什么意思?我理解包和导入,但这里只有一个包,main$foo应位于main包中。它不需要导入。

我的包变量发生了什么,它在超出范围后似乎不在包中?


附录

  

因此,如果您使用了$::foo,或者再次使用our $foo;创建了另一个别名,那么您的程序将按预期工作。 cmj

我们试试吧......

#! /usr/bin/env perl
#
# use warnings;
use strict;
use feature qw(say);

{
    our $foo = "bar";
    say "Foo = $foo";
}

our $foo;          # Redeclared
say "Foo = $foo";  # This is line #12

现在,打印出来:

bar
bar

正如所有回答的人所指出的那样,our只是为同名的包变量创建一个别名,并且词法作用域。这意味着一旦别名超出范围,我就可以使用$main::foo访问$foo的值。这是我以前从未意识到的事情。

但是,正如cjm指出的那样,重新声明our $foo;会恢复别名,而现有的$main::foo会将别名更改为新的$foo。当我重新声明our $foo;时,$foo的值已恢复

关于our变量的事情之一可能会让人感到困惑。你看到一个声明our $foo;,突然不仅存在这个变量,而且它有一个神秘的价值。您必须搜索程序以查看该值可能来自何处。

3 个答案:

答案 0 :(得分:5)

Our声明包变量的词法别名。这意味着它的范围就像my一样。不同之处在于它由包变量支持,因此当您退出范围时,变量不会消失。只有别名消失了。

因此,如果您使用$::foo或再次使用our $foo创建了另一个别名,您的程序将按预期工作。

答案 1 :(得分:2)

Our不表示包装范围。

  

我们的声明声明了一个包变量的别名   在整个词汇范围内都可以看到,甚至是整个包装   边界。

这意味着当声明它的块的词法范围结束时,它会超出范围。

答案 2 :(得分:2)

  

“变量”$ foo“未在./test.pl第12行导入。”意思?

perldiag说:

  

实际上使用“use strict”时,您引用了一个全局变量   你显然认为是从另一个模块导入的,因为   导出的其他同名(通常是子程序)   那个模块。这通常意味着你把错误的搞笑角色放在了   你变量的前面。

这没有任何意义,因为你没有导入任何东西。它不应该由您的代码发出。 Perl试图帮助诊断严格的错误,但是错了。忽略警告。


  

但是,我们的变量假设是包范围

那不是真的。 our创建一个词法变量,就像my一样。该变量别名为具有相同名称的包变量。

package Foo;
our $x;         # Equivalent to: alias my $x = $Foo::x;
$Foo::x = 123;
package Bar;
$Bar::x = 456;
print("$x\n");  # 123

alias由Data :: Alias提供。)