cale2 问了一个很难的问题
今天卡尔2拒绝问简单的问题。我们来看它今天问了什么难题:
<cale2> 我需要一份关于 * vs $_ vs $ 的指南。
这个问题问得多么好。那三种东西都是语法糖, 因为上下文转换, 它们能很好地避免折行和更少的 bugs。
我们从我们的老朋友主题变量 $_
开始。在 Perl 5 中它刚好出现在每个 sub 的外面。在 Perl 6 中它出现在块的默认值之外。
my &block = { 'oi‽' };
&block.signature.say;
# OUTPUT«(;; $_? is raw)
»
块的默认签名是一个名为 $_
的位置参数。因此每个块都有一个主题变量 $_
。还有其他设置 $_
主题变量的语句,而不引入一个新的块,像 with 和 given (given 的确引入了一个块,但它是特殊的,我在这里不说明细节)。
say $_ with 42;
# OUTPUT «42
»
因为它是默认的, Perl 6 会在很多地方期待它的出现。最突出的是当没有对象方法调用时。
$_ = 42; say 'oi‽' when 42;
.say;
# OUTPUT«oi‽
42
»
一个单独的 $
实际上是两个(有一点)的东西。在签名中,它是一个我们永远不能使用的位置参数标记(也许是因为我们不在乎),因为它没有名字,因此在它所应用的例程中不引入符号。它对于 protos 和免费的浮点签名很有用。它的第二个用途实际上引入了一个容器,也没有符号。它也是一个状态变量,它的初始化器(如果有一个)不被处理为状态,并将被调用多于一次。我们可以使用匿名状态变量来计数东西。
my @a = <a b c d>;
for @a { say @a[$++] };
# OUTPUT«a
b
c
d
»
我们可以滥用匿名变量 $
在列表赋值中跳过我们不想要的值。当我们从一个子例程中得到一个短的列表时会很简洁。
my ($,$,$c) = <a b c d>;
say $c;
# OUTPUT«c
»
我很享受这样的事实,我懒得给一次性变量起名字。认知负荷越小越好。
Whatever *
是问题的难点。有时它是一个语法糖标记,我们用它来告诉 Perl 6 我们不关心什么将被选中。在其他时候,它意味着 Inf, 意思是它们中的所有。
my @a = <a b c d>;
put @a.pick(*);
# OUTPUT«c d b a
»
如果在参数列表中使用一个单独的 *
,它将变成单例 Whatever。由于我们可以要求签名中的值,我们可以为 muiti
s 提供接口。
multi sub foo(Int $i){ $i * 42 };
multi sub foo(Whatever){ <42 oi‽ ♥>.pick };
say foo(*);
# OUTPUT«♥
» (your results may vary)
如果我们在包含运算符或调用的语句中使用 *
,它会形成一个没有作用域的块,并像一个占位符变量一样运行,而不会丢失该块由 *
生成的信息。生成的 Callable 的类型是 WhateverCode 并且当提供了 Sub 或方法时, 例程可以在它上面采取不同的行动。与真正的占位符变量相反, Whatever 可以用在 where 子句中。
sub foo($a where * < 10){}
对于他的问题, 这不是一个完整的答案。这就是为什么我建议卡尔2去阅读文档。
感觉还没有完全说清楚这三个语法糖。
网友评论