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

jjm*_*elo 10 perl6 raku

此代码不返回任何内容

<foo bar ber>.map: { $^a.comb.map: { $^b.say}};
Run Code Online (Sandbox Code Playgroud)

它包含两个嵌套映射,它们都在接收器上下文中.它应该不起作用,因为在沉没上下文中沉没的列表是无操作.

但是,这有效:

<foo bar ber>.map: *.say; # OUTPUT: «foo?bar?ber?»
Run Code Online (Sandbox Code Playgroud)

它又是接收器上下文中的列表.那它为什么有效呢?

Jon*_*ton 10

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

<foo bar ber>.map({ $^a.comb.map: { $^b.say}}).flat # OUTPUT: «f?o?o?b?a?r?b?e?r?»
Run Code Online (Sandbox Code Playgroud)

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

(<foo bar ber>.map: *.say).list;
Run Code Online (Sandbox Code Playgroud)

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

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


Eli*_*sen 5

我想,这是因为只有在最后的声明map沉没:

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
Run Code Online (Sandbox Code Playgroud)

所以内部map不会沉没,因此不会运行,因为它是sink-all内部映射(通过sink方法在迭代器上调用)使事情发生.

  • 这是事实,但并没有解决问题中的真正混淆,即`map`根本不会返回`List`. (3认同)