我最初的计划是使用两个once {next}
块来跳过文件中的前两行(此处将 a 模拟为多行字符串):
for "A\nB\nC\n".lines() -> $line {
once {next}
once {next}
put $line;
}
Run Code Online (Sandbox Code Playgroud)
但它只跳过了一次迭代而不是两次,输出如下:
B
C
Run Code Online (Sandbox Code Playgroud)
而不是我所期望的:
C
Run Code Online (Sandbox Code Playgroud)
显然,单个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 ';
}
Run Code Online (Sandbox Code Playgroud)
输出:
A: many
A: many
B: once
B: many
B: many
C: once
C: once again
C: many
C: many
Run Code Online (Sandbox Code Playgroud)
(此处的示例代码是https://docs.raku.org/language/control#once上代码的修改版本)。
这是一个错误还是我误解了once {next}
?
Jon*_*ton 12
所述once
构建体的语义与闭合克隆相关联; 由于for
是根据 定义的map
,我们可以将for
循环块视为每个循环克隆一次的闭包,并且该克隆用于循环的所有迭代。once
块的运行仅在第一次调用该闭包克隆时完成。也就是说,它是闭包级别的属性,而不是once
块本身。
完全相同的语义适用于state
变量初始值设定项,它们以相同的方式定义(即,它们具有once
语义)。因此,这也表现出相同的行为:
for "A\nB\nC\n".lines() -> $line {
state $throwaway-a = next;
state $throwaway-b = next; # this `next` never runs
put $line;
}
Run Code Online (Sandbox Code Playgroud)
可以选择替代语义,但是每个once
(以及每个state
变量)指标意味着它们中的每一个都需要一个额外的状态。
就原始问题而言,更清晰的解决方案是:
for "A\nB\nC\n".lines().skip(2) -> $line {
put $line;
}
Run Code Online (Sandbox Code Playgroud)