代码之家  ›  专栏  ›  技术社区  ›  Sean

逗号运算符上的三角形减法如何知道生成所有列表的列表?

  •  10
  • Sean  · 技术社区  · 6 年前

    在Perl6中,对逗号运算符进行三角形缩减会生成一个列表列表,每个列表都从输入列表中添加一个连续的元素:

    > [\,] 1..5
    ((1) (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5))
    

    非常好!但是最近我想知道它是如何工作的。

    如果 op 是一个任意的运算符, [op] @list 应该和 @list[0] op @list[1] op ... op @list[*-1] . 据我所知, [\op] 然后应该是所有中间值的列表。但这似乎意味着 [\op] @list 应评估为 (@list[0], @list[0] op @list[1], @list[0] op @list[1] op @list[2], ...) . 在我原来的情况下 操作 , ,则输出列表的第一个元素应该只是 @list[0] 但是它不是;它是一个单件清单 (@list[0],) .

    原始的三角形约简如何知道使其输出的第一个元素成为单例列表?

    如果我编写自己的列表构建例程,它会像我预期的那样工作:

    > sub foo { |$^a, $^b }
    sub foo ($a, $b) { #`(Sub|93971926296448) ... }
    > [[&foo]] 1..5
    (1 2 3 4 5)
    > [\[&foo]] 1..5
    (1 (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5))
    
    2 回复  |  直到 6 年前
        1
  •  10
  •   Jonathan Worthington    6 年前

    这是因为 infix:<,> 运算符是列表关联的。关联性通常是关于决定事物是左组还是右组(或者根本不是)。Perl6还认识到一些运算符以“平面”方式进行关联,我们只希望将由运算符分隔的所有值立即提供给运算符实现。

    如果我们声明一个具有默认关联性的运算符并使用它:

    sub infix:<a>(*@a) {
        say @a.perl;
        return @a.elems;
    };
    say [\a] 1..5;
    

    然后,只使用一对元素调用它,给出输出:

    [1, 2]
    [2, 3]
    [2, 4]
    [2, 5]
    (1 2 2 2 2)
    

    但是,通过添加 is assoc('list') 特质:

    sub infix:<a>(*@a) is assoc('list') {
        say @a.perl;
        return @a.elems;
    };
    say [\a] 1..5;
    

    然后输出为:

    [1]
    [1, 2]
    [1, 2, 3]
    [1, 2, 3, 4]
    [1, 2, 3, 4, 5]
    (1 2 3 4 5)
    

    这是怎样 中缀:& lt;& gt; 获取其漂亮的三角形缩减行为。

        2
  •  4
  •   raiph    6 年前

    我正要出版时,乔纳森发表了他的答案。我相信他对任何事情的最坏的回答比我对任何事情的最好的回答都要差,但嘿,这就是我所拥有的,即使这是完全错误的。


    离开几天后回来,我仍然认为我的答案有点帮助,尽管乔纳森的答案。总之,我重写了我的答案,以最好地提炼出它的简单本质。


    这不是三角形的问题。这与基础的基本减少量是一致的。

    应用 , 对单个元素生成单个元素列表

    你写道:

    [\op] @list 应评估为 (@list[0], @list[0] op @list[1], ...) .

    不一定。每 the doc for the reduce routine (加上我的补充) 强调 ):

    如果 @list 只包含一个元素, 如果可能的话,该运算符将应用于该单个元素 ;如果不是,则返回元素本身。

    可以使用 ,请 使用单个元素,生成单个元素列表:

    say .gist given 42   ; # 42
    say .gist given 42 , ; # (42)
    say .perl given 42 , ; # (42,)
    

    因此:

    say [,]  42;    # (42)
    say [,]  42,99; # (42 99)
    

    所以一个普通的逗号减法总是产生一个列表,即使它是一个元素的减法。三角形约简如下:

    say [\,] 42;    # ((42))
    say [\,] 42,99; # ((42) (42 99))
    
    推荐文章