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

问题描述 投票:0回答:2

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
将块视为一个表达式,而 sometimes 会导致它运行? 或者 Rakudo 的行为是否不正确? 还是我的理解有误?

expression raku do-notation rakudo
2个回答
5
投票

更新 请考虑删除此答案。我实际上没有删除它,因为我不被允许这样做,而这又是因为它是公认的答案。请参阅评论以获取更多信息,或者更好的是,忽略此答案并依赖@BradGilbert 的答案。

据我所知:

  • 像所有“语句前缀”一样,

    do
    消耗其右侧的“blorst”(块或语句)并将其视为语句。

  • do
    唯一的特殊功能是它计算(最后一个)语句的值。我认为这是其运作中唯一具有“表达”意义的意义。

这与以下行为相互作用,这些行为与

do
无关:

  • 当“裸”块 (

    {...}
    ) 被视为语句时,它会运行该块。

  • 其他块,被视为语句,不要(或不应该)运行。

我认为文档句子的修复类似于:

运行块的最简单方法是在它不能表现得像独立语句一样,在它之前写上

do

虽然我不知道文档在哪里/是否谈论裸块和其他块之间的区别。


1
投票

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
与裸块一起使用时,它充当语句形式,但也返回最后评估的值。

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
(块或语句)而不仅仅是语句,因为将块转换为语句只是为了撤消该操作并将其转换为语句没有多大意义类似表达式的块,以便它将返回其最后一个值。

基本上

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

© www.soinside.com 2019 - 2024. All rights reserved.