我的词汇范围

时间:2013-12-19 14:17:06

标签: perl

几乎每个编写的perl程序都使用这个习语:

{
open(my $fh, '>>', $filename) || die "you lose";
print $fh $blah;
}

然而,我不想死,我想跳过印刷品。 所以我写道:

{
print "you lose\n" unless (open(my $fh, '>>', $filename) and print $fh $blah);
}

并获取“不能使用未定义的值作为./o.pl第5行的符号引用”。

删除my(错误表单)会消除此错误,如下所示:

{
my $fh;
print "you lose\n" unless (open($fh, '>>', $filename) and print $fh $blah);
}

但为什么?

为什么在破损的代码中,$fh不会open(my $fh...存在到块的结尾(})?

4 个答案:

答案 0 :(得分:10)

my在语句结束前不生效。

出于同样的原因,my $x = $x将不会在声明的右侧看到新的$x。它会看到旧的$x

例如

use strict;
use warnings;

my $x = 42;

{
    my $x = $x + 1;
    print "inside, x = $x\n";
}

print "outside, x = $x\n";

打印:

inside, x = 43
outside, x = 42

您的open语句大致相当于上面的内部my语句。如果您在外部范围内声明$fh,则会发生令人惊讶的乐趣:您可能最终打印到错误的文件。

答案 1 :(得分:5)

您可能更喜欢

{
  open(my $fh, '>>', $filename) || warn "you lose";
  print $fh $blah if $fh->opened;
}

当然,如果您愿意,也可以删除warn

如果您的Perl 5早于版本14,那么您需要添加

use IO::File

到代码的标题。

答案 2 :(得分:4)

如果您在程序中添加strictwarnings,则会收到更多有用的错误消息:

use strict;
use warnings;

{
   my $filename = "test.txt";
   print "you lose\n" unless (open(my $fh, '>>', $filename) 
         and print {$fh} $blah);
}

__END__
Global symbol "$fh" requires explicit package name at test.pl line 6.
Global symbol "$blah" requires explicit package name at test.pl line 6.
Execution of test.pl aborted due to compilation errors.

问题在于您无法在同一语句中声明和使用词法变量。 $fh只有上有open的行后才可用。

答案 3 :(得分:3)

您不能声明词法变量并在同一语句中使用它。

但你可以,

open($_, '>>', $filename) and print $_ $blah for my $fh;

open($_, '>>', $filename) ? print $_ $blah : print "you lose\n"
  for my $fh;