【问题标题】:After first "once {next}" block, other same-scoped "once" blocks fail to execute在第一个“once {next}”块之后,其他相同范围的“once”块无法执行
【发布时间】:2020-07-15 22:23:46
【问题描述】:

我最初的计划是使用两个 once {next} 块来跳过文件中的前两行(这里将 a 模拟为多行字符串):

for "A\nB\nC\n".lines() -> $line {
    once {next}
    once {next}
    put $line;
}

但它只跳过了一次迭代而不是两次,输出如下:

B
C

而不是我的预期:

C

显然,单个once {next} 以某种方式取消了同一范围内所有剩余的once 块:

my $guard = 3;

loop {
    last if $guard-- <= 0;
    once { next };
    once { put 'A: once ' };
    once { put 'A: once again' };
    put 'A: many ';
}

$guard = 3;
loop {
    last if $guard-- <= 0;
    once { put 'B: once ' };
    once { next };
    once { put 'B: once again' };
    put 'B: many ';
}

$guard = 3;
loop {
    last if $guard-- <= 0;
    once { put 'C: once ' };
    once { put 'C: once again' };
    once { next };
    put 'C: many ';
}

输出:

A: many
A: many
B: once
B: many
B: many
C: once
C: once again
C: many
C: many

(此处的示例代码是 https://docs.raku.org/language/control#once 代码的修改版本)。

这是一个错误还是我误解了once {next}

【问题讨论】:

  • 顺便说一下,跳过前 X 行的另一种方法是使用匿名自增变量:for "A\nB\nC\n".lines() -&gt; $line { next unless $++ &gt; 1; put $line;}

标签: raku


【解决方案1】:

once 构造语义与闭包克隆相关联;由于for 是根据map 定义的,我们可以认为for 循环的块就像一个闭包,每个循环克隆一次,并且该克隆用于循环的所有迭代。 once 块的运行仅在第一次调用该闭包克隆时完成。也就是说,它是闭包级别的属性,而不是once 块本身。

同样的语义适用于state 变量初始化器,它们以相同的方式定义(即,它们具有once 语义)。因此,this this 也表现出相同的行为:

for "A\nB\nC\n".lines() -> $line {
    state $throwaway-a = next;
    state $throwaway-b = next; # this `next` never runs
    put $line;
}

可以选择替代语义,但是 per-once(以及 per-state 变量)指示符意味着它们中的每一个都需要一个额外的状态。

就最初的问题而言,更清晰的解决方案是:

for "A\nB\nC\n".lines().skip(2) -> $line {
    put $line;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2018-09-22
    • 2011-10-11
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多