映射、嵌套映射和接收器上下文
Maps, nested maps and sink context
此代码returns无
<foo bar ber>.map: { $^a.comb.map: { $^b.say}};
它包含两个nested maps, both of them in sink context. it shouldn't work, because a list sunk in a sink context is a no-op。
但是,这有效:
<foo bar ber>.map: *.say; # OUTPUT: «foobarber»
它又是接收器上下文中的列表。那么它为什么有效?
我认为这是因为只有 map
的 last 语句是 not 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
方法)让事情发生。
一个map
不是return一个List
,而是一个Seq
。 Seq
是一次性 Iterable
值序列,在接收器上下文中,它将迭代其底层迭代器并丢弃生成的值。这就是为什么接收器上下文中的 map
会迭代,但只有一层深。添加 .flat
以吸收内部值(通过将它们展平为单个顶级序列):
<foo bar ber>.map({ $^a.comb.map: { $^b.say}}).flat # OUTPUT: «foobarber»
A List
确实不会在接收器上下文中迭代它的值,因为 List
是一种数据结构,它甚至可以记住延迟生成的值,以便可以重复索引它们。的确,在做:
(<foo bar ber>.map: *.say).list;
不产生任何输出,因为 Seq
被强制转换为 List
,它在接收器上下文中不执行任何操作。
对可迭代数据的内置操作很少 return a List
,因为保留数据是过早的承诺。将这些操作链接在一起并让数据一次流过一个项目通常很有用,而不必在每个中间步骤都保存在内存中。这就是 Seq
的功能,以及为什么这么多东西 return 而不是 List
.
此代码returns无
<foo bar ber>.map: { $^a.comb.map: { $^b.say}};
它包含两个nested maps, both of them in sink context. it shouldn't work, because a list sunk in a sink context is a no-op。
但是,这有效:
<foo bar ber>.map: *.say; # OUTPUT: «foobarber»
它又是接收器上下文中的列表。那么它为什么有效?
我认为这是因为只有 map
的 last 语句是 not 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
方法)让事情发生。
一个map
不是return一个List
,而是一个Seq
。 Seq
是一次性 Iterable
值序列,在接收器上下文中,它将迭代其底层迭代器并丢弃生成的值。这就是为什么接收器上下文中的 map
会迭代,但只有一层深。添加 .flat
以吸收内部值(通过将它们展平为单个顶级序列):
<foo bar ber>.map({ $^a.comb.map: { $^b.say}}).flat # OUTPUT: «foobarber»
A List
确实不会在接收器上下文中迭代它的值,因为 List
是一种数据结构,它甚至可以记住延迟生成的值,以便可以重复索引它们。的确,在做:
(<foo bar ber>.map: *.say).list;
不产生任何输出,因为 Seq
被强制转换为 List
,它在接收器上下文中不执行任何操作。
对可迭代数据的内置操作很少 return a List
,因为保留数据是过早的承诺。将这些操作链接在一起并让数据一次流过一个项目通常很有用,而不必在每个中间步骤都保存在内存中。这就是 Seq
的功能,以及为什么这么多东西 return 而不是 List
.