【问题标题】:Lexical scope of mymy 的词法范围
【发布时间】:2013-12-19 14:17:05
【问题描述】:

几乎每个编写的 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 (bad form) 可以消除此错误,如下所示:

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

但是为什么?

为什么在损坏的代码中,从open(my $fh... 到块结束(})不存在$fh

【问题讨论】:

  • “几乎每个编写的 perl 程序都使用这个习语” 哦,如果那是真的!

标签: perl


【解决方案1】:

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,将会发生令人惊讶的乐趣:您可能最终会打印到错误的文件。

【讨论】:

  • 感谢您的明确解释。 PS,在我看来,perl 在“最少惊喜”的原则上在这里失败了。
  • 如果您想要最少的意外(或至少通知意外),请启用严格和警告
【解决方案2】:

你可能更喜欢

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

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

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

use IO::File

到代码的标题。

【讨论】:

    【解决方案3】:

    如果您将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 的行之后可用。

    【讨论】:

    • 是和否;新词汇由 my “返回”,因此可以使用。您不能在同一语句中引用词法 按名称
    • 这是有道理的。该名称只会在语句执行后添加到该范围的符号表中吗?
    • 不,它是在编译时添加的,但仅限于特定范围的语句。
    【解决方案4】:

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

    你可以,

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

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

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      相关资源
      最近更新 更多