您在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更好或至少相同。
这里唯一的例外是当要进行map
ped,grep
ped等操作的对象处于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。