逗号运算符的三角归约如何知道制作所有列表的列表?
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:<,>
是如何获得良好的三角形缩减行为的。
【讨论】:
这个答案很酷,我看到 OP 已经接受了它,但我认为它解释了三角缩减如何与列表关联操作一起工作,而不是回答 OP 的问题,该问题特定于第一个1
而是 (1)
用于 ,
操作。按照我认为是这个答案的指导,人们会写sub infix:<a>(*@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))
【讨论】:
以上是关于逗号运算符的三角归约如何知道制作所有列表的列表?的主要内容,如果未能解决你的问题,请参考以下文章