Perl6一线执行。主题如何更新?

时间:2019-01-25 00:29:40

标签: command-line perl6

从标准输入一次执行一个班轮处理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所说的)。如何在不重新输入区块的情况下更新其值?

我想念什么?

3 个答案:

答案 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

我尝试仅添加一个裸露的块,但是编译器添加循环的方式导致该块不起作用。


通常ENTERLEAVE的作用域为块{},但如果没有,则它们的作用域也为“ 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 phasersfor $*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 标志背靠背运行本质上重复的脚本会产生有趣的结果。 BEGINENTERLEAVEEND 出现在完全相同的位置,按每次调用一次的顺序重复:

~$ 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