【问题标题】:What's the difference in delayed evaluation of code in subroutines for Perl's 5.8 vs. 5.10 and 5.12?Perl 的 5.8 与 5.10 和 5.12 的子例程中的代码延迟评估有什么区别?
【发布时间】:2011-02-15 15:01:00
【问题描述】:

这段代码在 Perl 5.8 下的行为与在 Perl 5.12 下的行为不同:

my $badcode = sub { 1 / 0 };
print "Made it past the bad code.\n";

当我在 5.8 下运行它时,即使我从未执行除法,我也会收到错误:

[brock@chase tmp]$ /usr/bin/perl -v

这是为 i486-linux-gnu-thread-multi 构建的 perl,v5.8.8

[brock@chase tmp]$ /usr/bin/perl badcode.pl
在 badcode.pl 第 1 行非法除以零。

[brock@chase tmp]$ /usr/local/bin/perl -v

这是为 i686-linux 构建的 perl 5,版本 12,subversion 0 (v5.12.0)

[brock@chase tmp]$ /usr/local/bin/perl badcode.pl
让它通过了错误的代码。

在 perl 5.10.1 下,它的行为与 5.12 下一样:

brock@laptop:/var/tmp$ perl -v

这是为 i486-linux-gnu-thread-multi 构建的 perl,v5.10.1 (*)

brock@laptop:/var/tmp$ perl badcode.pl
让它通过了错误的代码。

我使用命名子例程得到相同的结果,例如

sub badcode { 1 / 0 }

我在 perl5100delta pod 中没有看到任何关于此的内容。这是一个未记录的更改吗?其他一些变化的意外副作用? (为了记录,我认为 5.10 和 5.12 做的是正确的事情。)

【问题讨论】:

  • 我不知道答案,但在我看来 Perl 5.10+ 也推迟了词法优化,例如预计算 1 / 0。不确定任何一种方式是否被认为是“正确的事情”。

标签: perl perl5.8


【解决方案1】:

我相信这是计划好的,我确实看到提到了 in perl5100delta.pod

常量折叠中的异常

现在是常量折叠例程 包装在异常处理程序中,并且 如果折叠引发异常(例如 试图评估 0/0), perl 现在保留当前的optree,而不是 而不是中止整个程序。 如果没有这种变化,程序将 如果他们有表达式,则不编译 碰巧产生异常, 即使那些表达在 永远无法到达的代码 运行。 (尼古拉斯·克拉克,戴夫 米切尔)

它只是与被零除异常有关,不会导致编译阶段中止。

【讨论】:

  • 谢谢,埃文。现在我需要弄清楚如何在 perl 5.8 下的测试中解决这个问题,因为我正在使用这段代码来测试边缘情况。 抱怨
  • @Brock :不确定它是否会起作用,因为我从来没有这样做过,但是您是否考虑过使用 eval 包装器捕获错误?
  • 对,但你可以做到$sub = eval 'sub { 1 / 0 }'eval 'require "DefinesCrashySub.pm"'
  • eval 技巧不起作用,因为我正在测试的是我 eval { $coderef->() } 的一些代码,并捕获错误以在其他地方处理。但是,即使在 perl 5.8 中,这也有效:my $zero = 0; my $badcode = sub { 1 / $zero }; print "Made it past the bad code.\n";
  • @Brock => 那是因为表达式中的变量阻止常量文件夹在编译期间减少它。如果只需要抛出异常,何乐而不为my $badsub = sub {die "badsub died\n"};
猜你喜欢
  • 1970-01-01
  • 2012-11-14
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 2018-09-03
  • 2014-01-25
  • 1970-01-01
  • 2016-12-02
相关资源
最近更新 更多