问题复现:
#!/usr/bin/perl
use warnings;
use strict;
sub fun {
my $var = "hello world";
doSth();
sub doSth {
print "var: $var\n";
}
}
fun();
报错信息:Variable "$var" will not stay shared at t.pl line 11.
出错原因
perl的sub声明是全局的,在fun()中声明的doSth()不是fun()的私有函数
第一次调用fun()时声明doSth(),并且其$var变量是第一次fun()中的'hello world'
如果第二次调用fun(),此时doSth()已经存在,不会再次声明,而此时调用doSth()打印的并不是此刻fun()中的$var,而是第一次fun()中的$var.之后的调用doSth已经和fun无关了,而且sub声明的doSth可以在任何地方使用
使用如下代码测试以上分析
#!/usr/bin/perl
use warnings;
use strict;
sub fun {
my $var = shift || "hello world";
print "fun var: $var\n";
sub doSth {
print "$var\n";
}
doSth();
}
fun();
fun("two");
fun("three");
输出:
Variable "$var" will not stay shared at t.pl line 19.
fun var: hello world
hello world
fun var: two
hello world
fun var: three
hello world
解决方案
#!/usr/bin/perl
use warnings;
use strict;
sub fun {
my $var = shift || "hello world";
## 使用闭包
my $doSth = sub {
print "var: $var\n";
};
$doSth->();
}
fun();
fun("two");
fun("three");
或者
#!/usr/bin/perl
use warnings;
use strict;
sub fun {
my $var = shift || "hello world";
## 使用符号表的类型团
no strict "refs";
*doSth = sub {
print "$var\n";
};
print "fun var: $var\n";
doSth();
}
fun();
fun("two");
fun("three");
或者
## 通过词法作用域变量控制
{
my $var;
sub fun {
$var = shift || "hello world";
doSth();
}
sub doSth {
print "$var\n";
}
}
fun();
fun("two");
fun("three");
解决方案在stackoverflow找到
http://stackoverflow.com/questions/25399728/perl-variable-will-not-stay-shared
本文探讨了Perl中子函数变量共享的问题及解决方案。通过具体代码示例展示了错误的原因,并提供了三种解决方法:使用闭包、利用符号表的类型团以及通过词法作用域变量控制。
5067

被折叠的 条评论
为什么被折叠?



