【问题标题】:Will Perl's $@ ever be undefined after an eval?Perl 的 $@ 在 eval 之后会不会被定义?
【发布时间】:2013-07-21 19:49:04
【问题描述】:

我正在编写Mastering Perl"Error Handling and Reporting" 章节。在perlvar$@ 条目中,它说:

来自最后一个 eval() 运算符的 Perl 语法错误消息。如果 $@ 是空字符串,则最后一个 eval() 解析并正确执行(尽管您调用的操作可能以正常方式失败)。

现在我想知道eval 何时可能无法正确执行,从而使$@ 具有未定义的值。有没有这样的案例?

【问题讨论】:

  • 这会返回一个空字符串:perl -MData::Dumper -e'$@=123; eval q{$@=456}; print(Dumper($@));' 但描述不正确。 $@ 被设置为die 的参数,如果它被执行的话。否则,它是一个空字符串。
  • 我不关心空字符串的情况。这是定义的行为。我问的是相反的情况。
  • $@ 如果没有执行 eval 也是空字符串:perl5.14.2 -E 'say q(\$@ is the empty string) if $@ eq q()'
  • 阅读答案/cmets,我建议将“正确执行”的确切定义放入问题中。每个人都有自己的想法。
  • 我不知道那个定义是什么,这个定义是问题的症结所在。

标签: perl eval


【解决方案1】:

这是一种方法(但在阅读之前请坐下来。;))

$@ = 123;
eval q{
  $@ = 456;
  print ">>>$@<<<\n";
  goto SKIP;
};

SKIP:
print ">>>$@<<<\n";

【讨论】:

  • @shawnhcorey 被认为是有害的:-P
  • Perl 中容易的事情很容易,困难的事情是可能的,但不可能的事情需要一些思考。 ;)
  • 一种方法可以做什么?我在这个中没有看到 eval 中的 undef 值。这很有趣,但离我的问题的答案还差得很远。
  • @briandfoy shawnhcorey 的回答表明我们可以通过使用goto 退出eval 来赋予$@ any 值。例如。 perl -E'eval{$@=undef; goto SAY}; SAY: defined $@ or say "undef"'.
  • @amon 尽管如此,这样的 eval() 执行正确。对于这个词的一些定义......
【解决方案2】:

BACKGROUND section of the Try::Tiny docs 包含一些关于如何破坏 $@ 以及为什么 Try::Tiny 会特别注意避免破坏的信息,并且始终测试 eval 的返回值而不是测试 $@ 的真实性。他们都在那里,因为有人 在某个时候遇到了他们,但我认为eval-in-DESTROY 场景是最有可能绊倒某人的场景。基本上,如果die 导致某个对象超出范围,并且该对象具有调用evalDESTROY,那么died 开始使用的值将无法挽回地丢失。假设DESTROY 中的eval 不会 抛出错误,$@ 将是"" 跟在外部eval 之后。

【讨论】:

  • 这不是在谈论破坏。它可以很容易地被不同的值破坏。
  • 请注意,$@ 在最后一两个版本中受到保护,不会受到此类破坏。
  • 我不在乎它是否被破坏,我根本不会询问您获得与预期不同的价值的情况。这些我都知道。
【解决方案3】:

谁说过将 $@ 设置为 undef?

“正确解析和执行的最后一个 eval()”没有任何意义:eval 在运行时不被解析。当然,它的意思是“表达式被正确解析和执行的最后一个 eval()”。换句话说,“最后一个 eval(),其表达式已编译并且在执行时没有抛出任何异常”。

>perl -MData::Dumper -e"$@=123; eval ''; print(Dumper($@));"
$VAR1 = '';

>perl -MData::Dumper -e"$@=123; eval '~~~'; print(Dumper($@));"
$VAR1 = 'syntax error at (eval 1) line 2, at EOF
';

>perl -MData::Dumper -e"$@=123; eval 'die q{x}'; print(Dumper($@));"
$VAR1 = 'x at (eval 1) line 1.
';

【讨论】:

  • 我说过 $@ 是 undef。我认为,您的示例都在正确评估并发现错误,就像他们应该做的那样。我的问题是,是否会出现无法正确执行的情况。如果不是,正如您所建议的那样,我认为文档需要更新,因此它并不意味着可能存在其他一些情况(即未正确解析和执行的情况)。
  • 存在未正确解析和执行的情况。在这种情况下,$@ 包含错误消息。我给出了一个未正确解析的示例,以及未正确执行的示例。正如我所解释的,“它”只能引用eval 的操作数。
  • 我重新输入了我的评论,因为我想编辑它,所以你的第一个实际上是一个回复。哪一个没有正确执行?如果其中任何一个,我会猜到第二个,但我不认为我会这样描述。
  • 第二次解析/编译失败。第三次执行失败。我已经说过我会如何描述它。 ("最后一个 eval(),其表达式已编译并且在执行时没有抛出任何异常")
  • 不抛出异常不等于执行失败。在我看来,#3 执行正常,完全按照 die 应该做的事情和 eval 应该做的事情做。模具实际上在运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 2022-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
相关资源
最近更新 更多