地图,嵌套地图和接收器上下文

时间:2018-05-19 08:23:08

标签: perl6 raku

此代码不返回任何内容

=SubtractChecking(A1, B7:M23)

它包含两个nested maps, both of them in sink context。它应该不起作用,因为a list sunk in a sink context is a no-op

然而,这有效:

=sum(a1, -sum(B7:M23))

并且它再次成为接收器上下文中的列表。那它为什么有用呢?

2 个答案:

答案 0 :(得分:10)

map不会返回List,而是SeqSeq是一次性Iterable值序列,在sink上下文中,它将迭代其底层迭代器并丢弃生成的值。这就是为什么sink上下文中的map将迭代,但只有一个深度。添加.flat以吸收内部值(通过将它们展平为单个顶级序列):

<foo bar ber>.map({ $^a.comb.map: { $^b.say}}).flat # OUTPUT: «f␤o␤o␤b␤a␤r␤b␤e␤r␤»

List确实不会在接收器上下文中迭代其值,因为List是一个数据结构,它甚至可以存储延迟生成的值,以便可以重复索引它们。确实,做:

(<foo bar ber>.map: *.say).list;

不产生输出,因为Seq被强制转换为List,它在接收上下文中什么都不做。

对可迭代数据的内置操作很少返回List,因为保留数据是过早的承诺。将这些操作链接在一起并使数据一次流过它们通常是有用的,而不是必须在每个中间步骤都保存在内存中。这是Seq启用的内容,以及为什么这么多内容返回而不是List

答案 1 :(得分:5)

我认为这是因为只有map last 语句 sunk:

class A {
    method sink() {
        say "sunk"
    }
}
<foo bar ber>.map: { A.new }     # doesn't show 'sunk'
A.new;                           # shows 'sunk' once
<foo bar ber>.map: { A.new; 1 }  # shows 'sunk' 3x

因此内部map不会被沉没,因此不会运行,因为它是内部地图上的sink-all(通过sink方法在迭代器上调用这会让事情发生。