我的测试是这样的:
use strict;
use warnings;
func();
my $string = 'string';
func();
sub func {
print $string, "\n";
}
结果是:
Use of uninitialized value $string in print at test.pl line 10.
string
Perl允许我们在定义函数之前调用它。但是,当函数使用仅在函数调用之后声明的变量时,该变量似乎未定义。这种行为是否记录在某处?谢谢!
答案 0 :(得分:12)
my
中记录了perl
的行为 - 归结为此 - $string
知道my
在范围内 - 因为my
告诉它如此。
my运算符声明列出的变量在词法上限制在封闭块,条件(if / unless / elsif / else),循环(for / foreach / while / until / continue),子例程,eval或do /要求/使用&#d;文件。
这意味着它的范围是'从他们第一次看到的地方开始#39;直到当前'块的结束括号。 (或者在你的例子中 - 代码的结尾)
但是 - 在您的示例$string
中还会分配一个值。
这个范围确定过程在编译时发生 - 其中perl检查它是否有效使用strict
。 (感谢#!/usr/bin/env perl
use strict;
use warnings;
my $string; #undefined
func();
$string = 'string';
func();
sub func {
print $string, "\n";
}
)。但是 - 它无法知道值是什么,因为在代码执行期间可能会发生变化。 (并且非常容易分析)
因此,如果你这样做,可能会更清楚一下:
$string
在这两种情况下, my
都在范围内 - 因为undef
发生在编译时 - 在子程序被调用之前 - 但它没有设置超出默认值{的值{1}}在第一次调用之前。
请注意这与:
形成鲜明对比#!/usr/bin/env perl
use strict;
use warnings;
sub func {
print $string, "\n";
}
my $string; #undefined
func();
$string = 'string';
func();
由于声明sub时出现了哪些错误,因此$string
不在范围内。
答案 1 :(得分:4)
首先,我会考虑这种未定义的行为,因为它会像my
一样跳过执行my $x if $cond;
。
尽管如此,这种行为目前是一致和可预测的。在这种情况下,如果保证未定义行为通知的优化没有退出,它的行为正好。
在编译时,my
具有声明和分配变量 [1] 的效果。 Scalars在创建时初始化为undef。数组和散列是空的。
my $string
,因此创建了变量。但是,由于您尚未执行任务,因此在第一次调用func
期间,它仍然具有默认值(未定义)。
此模型允许通过闭包捕获变量。
示例1:
{
my $x = "abc";
sub foo { $x } # Named subs capture at compile-time.
}
say foo(); # abc, even though $x fell out of scope before foo was called.
示例2:
sub make_closure {
my ($x) = @_;
return sub { $x }; # Anon subs capture at run-time.
}
my $foo = make_closure("foo");
my $bar = make_closure("bar");
say $foo->(); # foo
say $bar->(); # bar