`do` 关键字 运行 是块还是将其视为表达式?

Does the `do` keyword run a block or treat it as an expression?

docs 声明“运行 不能成为独立语句的块的最简单方法是在它之前写 do”并提供以下示例:

# This dies half of the time 
do { say "Heads I win, tails I die."; Bool.pick } or die; say "I win.";

然而,do 似乎并没有导致所有块都变成 运行。特别是,它似乎没有 运行 带有签名的块:

do -> $a = 42 { say "ran with $a"; 0 } or die; say 'done'; # OUTPUT: «done»

那么说 do 将一个块视为一个 有时 导致它成为 运行 的表达式会更好吗?或者 Rakudo 在这里的行为不正确?还是我的理解有误?

阿法克:

  • 像所有“语句前缀”一样,do 消耗其右侧的“blorst”(块或语句)并将其视为语句。

  • do 唯一的特殊能力是它计算出(最后)语句的值。我想这是唯一在操作上有“表达”感的感觉了。

这与以下行为交互,这些行为与 do 无关:

  • 当“裸”块 ({...}) 被视为语句时,它 运行 是块。

  • 其他的块,当作语句,不要(或shouldn't),运行.

我认为对 doc 句子的修正是这样的:

The simplest way to run a bare block where it cannot be is not behaving as a stand-alone statement is by writing do before it"

虽然我不知道where/if 文档谈到了裸块和其他块之间的区别。

do 关键字将语句转换为表达式。

my @b = do for @a { $_² if $_ %% 2 }

my $c = do if @b > 4 { +@b } else { 3 }

裸块可以是语句:

my $a = 1;
say $a;
{
  my $a = 2;
  say $a;
}
say $a;

也可以是表达式:

my $code = { … }

当您将 do 与裸块一起使用时,它充当语句形式,而且 return 计算最后一个值。

my $result = do { say 'hi'; 5 }
# hi

say $result;
# 5

另一方面,尖块始终是一个表达式。

my $code = -> $ { … }

即使你没有在任何地方分配它

say 'a';
-> { say 'hi' }
do -> { say 'bye' }
say 'b';

# a
# b

对已经是表达式的内容使用 do 毫无意义。


请注意,编译器中的 do 关键字采用 blorst(块或语句)而不仅仅是语句,因为将块变成语句没有多大意义撤消它并将它变成一个类似表达式的块,这样它将 return 它的最后一个值。

基本上blorst只捕获语句,但它直接捕获块类型的语句以简化编译器的内部结构。