Perl “do { … } if …”作为表达式

Perl “do { … } if …” as expression

my $x = do { 3; } if 1; say $x # works

my $x = (do { 3; } if 1); say $x # syntax error

怎么会?如果 do 块是一个表达式,为什么不能用括号括起来呢?如果不是,第一个如何解析?

问题不在于 do,而是后缀 if。该后缀不能出现在括号内:

$ perl -E 'my $x = ( 1 if 1); say $x'
syntax error at -e line 1, near "1 if"
Execution of -e aborted due to compilation errors.

相反,您可以在其中一个分支中使用带有 do 的条件运算符 ?:

$ perl -E 'my $x = ( time % 2 ? do { 1 } : () ); say $x'

一个compound statement用于流量控制(if BLOCK),还有一个带有语句修饰符(这里使用后缀if), 不能出现在括号内。

这个限制是有道理的,因为这样的语句 may or may not return 一个值

if executes the statement once if and only if the condition is true.

(原文强调)


旁注。第一个示例运行时没有警告,但它有 未定义的行为,这是必须避免的。从本节结尾开始 Statement Modifiers in perlsyn

NOTE: The behaviour of a my, state, or our modified with a statement modifier conditional or loop construct (for example, my $x if ...) is undefined. The value of the my variable may be undef, any previously assigned value, or possibly anything else. Don't rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.

(原文强调)

这个的任何实例都应该被重写,Perl::Critic 有一个 ,这样更容易找到它们

if 1 是一个 语句 修饰符。 my $x = do { 3; }是一个语句; do { 3; } 是一个 表达式 .

my $x = do { 3; } if 1;

实际上等同于

( my $x = do { 3; } ) if 1;

请注意,您不应有条件地执行 my。 (更准确地说,您不应该使用尚未执行的 my 变量。您的代码在技术上没有问题,因为 my 总是在使用 $x 之前执行。)


由语句修饰符 (if 1) 修饰的表达式 (my $x = do { ... }) 是一个语句。

括号内必须是表达式,而不是语句

你做不到

  • ( $x = 3; )
  • ( sub f { } )
  • ( if (f()) { g() } )
  • ( g() if f(); )
  • ( g() if f() )

你懂的。