* vs $_ vs $

作者: 焉知非鱼 | 来源:发表于2017-02-04 21:53 被阅读19次

    cale2 问了一个很难的问题

    今天卡尔2拒绝问简单的问题。我们来看它今天问了什么难题:

    <cale2> 我需要一份关于 * vs $_ vs $ 的指南。

    这个问题问得多么好。那三种东西都是语法糖, 因为上下文转换, 它们能很好地避免折行和更少的 bugs。

    我们从我们的老朋友主题变量 $_ 开始。在 Perl 5 中它刚好出现在每个 sub 的外面。在 Perl 6 中它出现在块的默认值之外。

    my &block =  { 'oi‽' };
    &block.signature.say;
    # OUTPUT«(;; $_? is raw)
    »
    

    块的默认签名是一个名为 $_ 的位置参数。因此每个块都有一个主题变量 $_。还有其他设置 $_ 主题变量的语句,而不引入一个新的块,像 withgivengiven 的确引入了一个块,但它是特殊的,我在这里不说明细节)。

    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。由于我们可以要求签名中的值,我们可以为 muitis 提供接口。

    multi sub foo(Int $i){ $i * 42 };
    multi sub foo(Whatever){ <42 oi‽ ♥>.pick };
    say foo(*);
    # OUTPUT«♥
    » (your results may vary)
    

    如果我们在包含运算符或调用的语句中使用 *,它会形成一个没有作用域的块,并像一个占位符变量一样运行,而不会丢失该块由 * 生成的信息。生成的 Callable 的类型是 Wh​​ateverCode 并且当提供了 Sub 或方法时, 例程可以在它上面采取不同的行动。与真正的占位符变量相反, Whatever 可以用在 where 子句中。

    sub foo($a where * < 10){}
    

    对于他的问题, 这不是一个完整的答案。这就是为什么我建议卡尔2去阅读文档。

    感觉还没有完全说清楚这三个语法糖。

    相关文章

      网友评论

        本文标题:* vs $_ vs $

        本文链接:https://www.haomeiwen.com/subject/pmssittx.html