逗号运算符的三角归约如何知道制作所有列表的列表?

Posted

技术标签:

【中文标题】逗号运算符的三角归约如何知道制作所有列表的列表?【英文标题】:How does a triangular reduction on the comma operator know to make a list of all lists? 【发布时间】:2018-12-15 21:04:55 【问题描述】:

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

> [\,] 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], ...)。在我原来op, 的情况下,输出列表的第一个元素应该只是@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))

【问题讨论】:

【参考方案1】:

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

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

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)

infix:&lt;,&gt; 是如何获得良好的三角形缩减行为的。

【讨论】:

这个答案很酷,我看到 OP 已经接受了它,但我认为它解释了三角缩减如何与列表关联操作一起工作,而不是回答 OP 的问题,该问题特定于第一个 1而是 (1) 用于 , 操作。按照我认为是这个答案的指导,人们会写sub infix:&lt;a&gt;(*@a) is assoc('list') return |@a 。但随后say [\a] 1..5 给出了(1 (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5)) 而不是((1) (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5))。这肯定是OP的重点吗?请参阅我的答案以了解我认为的答案。我要疯了吗?【参考方案2】:

乔纳森发布他的答案时,我正要发布。我会相信他对任何事情的最糟糕的回答,而不是我最好的回答,但嘿,这就是我所拥有的,即使它完全错误。


虽然离开并在几天后返回,但我仍然认为我的回答有些帮助,尽管乔纳森是这样。 Anyhoo,我已经重写了我的,以最好地提炼它的简单本质。


这与三角形无关。这与基本的基本减少是一致的。

, 应用于单个元素会生成单个元素列表

你写道:

[\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))

【讨论】:

以上是关于逗号运算符的三角归约如何知道制作所有列表的列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何删除最后一个数字中的逗号?

逗号分隔的列表正则表达式 [重复]

逗号运算符返回参数列表中的第一个值而不是第二个值?

我想在cpp中实现python列表,但卡在重载下标运算符[]和逗号,[关闭]

如何使用 SQL 查询创建逗号分隔的列表?

手撸golang 四则运算 计算器 yacc 归约