2

I was looking at this question, and while I was playing around, I came across this:

#! /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

Yes, I do have use warnings; turned off...

When I run this, I get:

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.

Hmmm... I get the same "Variable "$foo" is not imported at ./test.pl line 12." error if I had done my $foo = "bar";. I would understand this when I use my because there is no variable $foo once we leave the block. But, our variables are suppose to be package scope. I could understand how $foo might not have a value at that point, but this?

Also, what does the "Variable "$foo" is not imported at ./test.pl line 12." mean? I understand packages and importing, but there's only a single package here, main. $foo should be in the main package. It doesn't need to be imported.

What is going on with my package variable that doesn't seem to be in the package after it falls out of scope?


Addendum

So if you used $::foo, or created another alias with our $foo; again, your program would work as expected. cmj

Let's try this...

#! /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

Now, this prints out:

bar
bar

As everyone who answered pointed out, our merely makes an alias to the package variable of the same name, and it's lexically scoped. That means once the alias goes out of scope, so did my ability to access the value of $main::foo with $foo. That's something I never realized before.

However, as cjm pointed out, redeclaring our $foo; restores the alias, and the already existing $main::foo is aliased back to a new $foo. When I redeclare our $foo;, the value of $foo is restored.

It's one of the things about our variables that can be so confusing. You see a declaration our $foo;, and suddenly not only does that variable exist, but it has a mysterious value. You have to search the program to see where that value could have come from.

4

3 回答 3

5

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

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

于 2014-03-05T15:18:33.530 回答
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 提供。)

于 2014-03-05T15:17:20.443 回答
2

我们没有指明包装范围。

我们的声明为包变量声明了一个别名,该别名将在其整个词法范围内可见,甚至跨越包边界。

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

于 2014-03-05T15:10:45.113 回答