您在Perl 6中打高尔夫球有哪些一般提示?我正在寻找可以应用于编码高尔夫问题的想法,这些想法至少在某些方面是Perl 6特有的(例如,“删除评论”不是答案)。请为每个答案发布一个提示。
请注意,Perl 6不是Perl 5,因此此问题不是重复的。有关Perl 5高尔夫的大多数技巧只是不适用于Perl 6。
您在Perl 6中打高尔夫球有哪些一般提示?我正在寻找可以应用于编码高尔夫问题的想法,这些想法至少在某些方面是Perl 6特有的(例如,“删除评论”不是答案)。请为每个答案发布一个提示。
请注意,Perl 6不是Perl 5,因此此问题不是重复的。有关Perl 5高尔夫的大多数技巧只是不适用于Perl 6。
Answers:
避免使用sub文字。在许多情况下,您可以简单地将其{}用于代码块。例如,不要编写以下代码。
sub ($a){$a*2}
而是使用块语法。如果只需要一个变量,这也使您可以使用$_,@_和%_占位符变量。如果您需要更多,可以使用$^a,$^b变量等。
{$_*2}
同样,在某些罕见的情况下,可以使用任何代码(尤其是当您具有简单表达式时)。该*替换占位符参数。
* *2
了解读取输入的功能。Perl 6具有许多有趣的功能,可以轻松地从ARGV或STDIN读取输入(如果ARGV上未指定任何内容),如果使用正确,则可以缩短代码。如果将它们作为文件句柄方法调用,则可以强制它们在特定的文件句柄上工作(例如STDIN,如果您从中读取,则很有用,但必须读取ARGV上的参数)。
get此函数仅获得一行,并自动将其斩断,因此您不必这样做。如果您只需要阅读一行,这将很有用。
lines此函数从文件或STDIN获取所有行。这是一个惰性列表,因此,如果将其与一起使用for,它将仅读取您需要的内容。例如。
say "<$_>"for lines
slurp这将读取整个文件或STDIN,并将结果作为单个字符串返回。
say "<$_>" for lines现在可以正常工作
警告:文字墙正在接近。随着时间的推移,我收集了很多小技巧。
已经提到过这一点,但我想重申一下。在TIO中,您可以将其写入my $f =页眉,将该块写入适当的代码,然后以开头;。到目前为止,这似乎是完成工作的最短方法(因为您无需关心读取任何输入,因此它会在参数中提供给您)。
另一种不错的方法是使用-n或-p开关,但我找不到使它在TIO中工作的方法。
也就是说,代替 thing.method(foo,bar),你可以做thing.method:foo,bar,并保存1个字符。不幸的是,出于明显的原因,您不能在结果上调用另一个方法,因此仅对块中的最后一个方法使用才有意义。
$_尽可能多地因此,有时使用单个列表参数比使用几个单独的参数更好。访问时$_,您可以仅以点开头来调用方法:例如.sort等于$_.sort。
但是,请记住,每个块都有自己的块 $_,因此外层块的参数不会传播到内层块。如果需要从内部块访问主功能的参数,则...
^如果不能使用,变量$_^在符号和变量名称之间插入一个,如下所示:$^a。这些仅在一个块内起作用。编译器首先计算块中有多少个,按字典顺序对它们进行排序,然后将第一个参数分配给第一个参数,第二个参数分配给第二个参数,依此类推。在^仅在可变的第一次出现所使用的需求。因此,{$^a - $^b}取2个标量并减去它们。唯一重要的是字母顺序,{-$^b + $^a}同一件事也是如此。
如果您想使用尖的块语法(如->$a,$b {$a.map:{$_+$b}}),最好在块的开头使用^将要在主块中不使用的每个参数(如)编写伪语句{$^b;$^a.map:{$_+$b}}(注意这是一种更好的高尔夫方式{$^a.map(*+$^b)}。我只是想炫耀这个概念。)
操作员功能强大,通常是完成工作的最短方法。特别是元符(需要运营商作为一个参数运营商)[],[\],X,<</ >>和Z是你的注意力的价值。不要忘记一个meta-op可以接受另一个meta-op作为参数(就像XZ%%我设法在这里使用的)。您也可以使用>>方法调用,它比映射便宜很多(@list>>.method代替@list.map(*.method),但要注意,它们并不相同!)。最后,在使用二进制文件之前,请<< >>记住,Z这样做通常会用更少的字符来完成相同的操作。
如果您将许多元操作相互叠加,则可以使用方括号指定优先级[]。当您堆积过多的运算符以致使编译器混乱时,这将节省您的时间。(这种情况很少发生。)
最后,如果你需要强迫事情BOOL,INT或STR,不使用方法.Bool,.Int和.Str,而是运营商?,+和~。甚至更好,只需将它们放入算术表达式中以将其强制为Int等等。获取列表长度的最短方法是+@list。如果您想计算2到列表长度的幂,只需说2**@list,它将做正确的事情。
$,@以及%在每个块中,每一次出现$(或@或%)指的是一个全新的标量(或阵列,或散列)状态变量(一个变量,其值保持在调用给块)。如果您需要一个状态变量,而该状态变量只需要在源代码中被引用一次,那么这三个是您的好朋友。(通常是$。)例如,在“ 逆数学循环”挑战中,可以使用它从数组中循环选择运算符,该数组由索引$++%6。
map,grep等的子形式。那意味着:做而map {my block},list不是做list.map({my block})。即使您设法使用list.map:{my block},这两种方法也会以相同的字节数出现。通常,在调用方法时需要在列表中加上括号,而在调用子方法时则不需要。因此,子方法总是比方法1更好或至少相同。
这里唯一的例外是当要进行mapped,grepped等操作的对象处于in中时$_。然后.map:{}明显跳动map {},$_。
&和|)代替&&和||。显然,它们短了1个字节。另一方面,必须通过将它们强制为布尔上下文来使其崩溃。始终可以使用来完成此操作?。在这里,您应该意识到!op强制布尔上下文,使用op和否定结果的元操作。
如果您有列表,并且想要将其转换为联结,请不要使用[&]和[|]。而是使用.any和.all。还有.none那些不能被结ops轻易地模仿。
&&并且||对于短路仍然有用吗?
有几个部分。
使用my声明的变量通常可以在my和变量名之间没有空格的情况下声明。my @a等同于my@a。
您可以使用反斜杠声明变量,以在变量名称之前删除符号,如下所示:
my \a=1;
(很遗憾,您不能删除空格:()
这很有用,因为以后您可以将它们仅用作裸变量名称。
a=5;
a.say
基本上,如果您在代码的其他位置多次使用变量,则可以节省字节。缺点是该变量需要初始化。
$!和$/这些预先声明的变量通常分别用于异常和regex匹配,但不需要使用进行定义my。
$!=1;
$/=5;
尤其有用的是$/用作数组,并使用快捷方式$后跟数字以访问$/数组的该元素;
$/=100..200;
say $5; #105
say $99; #199
...代替first通常,如果要查找与某些条件匹配的第一个数字,&f可以将其表示为:
first &f,1..*
但是,您可以使用...运算符:
+(1...&f)
如果必须从头开始0,则可以-1事后代替+。
如果要获取@a具有condition 的列表中第一个元素的索引&f,通常可以执行以下操作:
first &f,@a,:k
代替:
(@a...&f)-1
(反之亦然,如果您想索引0)。以相同的方式,您可以使所有元素达到第一个通过条件的元素。
不利的一面是列表必须在某个点通过条件,否则...操作员将尝试从列表末尾推断,并很可能引发错误。您也不能在左侧使用任何代码,因为它将被解释为序列的一部分。
say (3² + 4², 2²⁰, 5⁻²)==>(25 1048576 0.04)。您可以在此处滥用的Unicode的完整列表在这里:docs.perl6.org/language/unicode_texas。