从标准输入一次执行一个班轮处理CSV行:
perl6 -ne 'my @a; $_.split(",").kv.map: {@a[$^k]+=$^v}; say @a; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"}';
输入:
1,1
1,1
^D
给出以下输出:
BEGIN
ENTER
1,1
[1 1]
1,1
[2 2]
LEAVE
END
在这里,我们可以看到一个衬板不是多次执行的块,因为ENTER和LEAVE移相器仅执行一次。
这很有意义,因为变量@a正在累积。如果一个衬板是一个块,则@a的值将每次重置。
我的问题是主题变量$ _如何更新?主题变量是一个Str(至少是$ _。^ name所说的)。如何在不重新输入区块的情况下更新其值?
我想念什么?
答案 0 :(得分:8)
当您添加-n
时,它将在您的代码周围添加一个for
循环。
您认为它添加了这样的内容:
for lines() {
# Your code here
}
编译器仅添加用于循环的抽象语法树节点,而无需实际添加块。
(
# Your code here
) for lines()
(它可能被解释为错误。)
要使其像第一个一样工作:
( # -n adds this
-> $_ { # <-- add this
# Your code here
}( $_ ) # <-- add this
) for lines() # -n adds this
我尝试仅添加一个裸露的块,但是编译器添加循环的方式导致该块不起作用。
通常ENTER
和LEAVE
的作用域为块{}
,但如果没有,则它们的作用域也为“ file ”
ENTER say 'ENTER file';
LEAVE say 'LEAVE file';
{
ENTER say ' ENTER block';
LEAVE say ' LEAVE block';
}
ENTER file
ENTER block
LEAVE block
LEAVE file
由于您的代码中没有任何块,因此所有内容的范围都限于“ 文件”。
答案 1 :(得分:2)
error:browser/delegate.sol:14:31: TypeError: Invalid type for argument in function call. Invalid implicit conversion from bytes4 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it.
watch_addr.call(bytes4(keccak256(abi.encode("register(string)"))));
command line argument在您的程序周围放了一个循环
-n
您使用的program execution phasers(for $*ARGFILES.lines {
# Program block given on command line
}
和BEGIN
)在编译时或程序块完成后为run once,因此它们不会成为一部分运行时循环的时间。
ENTER块移相器将在每个块进入时间运行,而
LEAVE块相位器将在每个块退出时间运行。因此,将为END
循环中读取的每一行运行这些相位器。
答案 2 :(得分:1)
更新 -- Rakudo 2020.10
运行您的原始累加器代码(使用 -ne
linewise 标志)会得到以下结果。请注意“final”一词如何出现在每一行中:
~$ perl6 -ne 'my @a; $_.split(",").kv.map: {@a[$^k]+=$^v}; say @a, " final"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"};' drclaw.txt
BEGIN
ENTER
[1 1] final
[2 3] final
[3 6] final
LEAVE
END
下面,使用 -ne
标志背靠背运行本质上重复的脚本会产生有趣的结果。 BEGIN
、ENTER
、LEAVE
和 END
出现在完全相同的位置,按每次调用一次的顺序重复:
~$ perl6 -ne 'my @a; .split(",").kv.map: {@a[$^k]+=$^v}; say @a, " final_a"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"}; my @b; .split(",").kv.map: {@b[$^k]+=$^v}; say @b, " final_b"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"};' drclaw.txt
BEGIN
BEGIN
ENTER
ENTER
[1 1] final_a
[1 1] final_b
[2 3] final_a
[2 3] final_b
[3 6] final_a
[3 6] final_b
LEAVE
LEAVE
END
END
但是,删除下面的 -ne
标志可以让您在 Raku 代码本身内运行 for lines() {...}
循环(单个脚本,而不是背靠背复制)。这个结果似乎更符合您的预期:
~$ perl6 -e 'my @a; for lines() {.split(",").kv.map: {@a[$^k]+=$^v};}; say @a, " final"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"};' drclaw.txt
BEGIN
ENTER
[3 6] final
LEAVE
END
我认为对您的问题的简短回答是 Phasers 尊重 Block/Loop 语义,但在脚本方面限制了他们向实现者报告的次数(显然每次调用只有一次)。但最终的区别在于,与内部 -ne
循环相比,for lines() {...}
命令行标志返回给用户的是 linewise linewise em>sans -ne
命令行标志。
最后,您始终可以使用 $_
中缀运算符强制重新加载 andthen
主题变量。也许这就是您一直在寻找的:
~$ perl6 -e 'my @a; for lines() {.split(",").kv.map: {@a[$^k]+=$^v} andthen $_.say }; say @a, " final"; ENTER {say "ENTER"}; BEGIN {say "BEGIN"}; LEAVE {say "LEAVE"}; END {say "END"};' drclaw.txt
BEGIN
ENTER
(1 1)
(2 3)
(3 6)
[3 6] final
LEAVE
END
[正在分析的测试文件,如下]。
~$ cat drclaw.txt
1,1
1,2
1,3
https://docs.raku.org/language/operators#index-entry-andthen