【问题标题】:Maps, nested maps and sink context地图、嵌套地图和接收器上下文
【发布时间】:2018-05-19 08:23:07
【问题描述】:

此代码不返回任何内容

<foo bar ber>.map: { $^a.comb.map: { $^b.say}};

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

但是,这是可行的:

<foo bar ber>.map: *.say; # OUTPUT: «foo␤bar␤ber␤»

它又是一个接收器上下文中的列表。那么它为什么会起作用呢?

【问题讨论】:

    标签: raku


    【解决方案1】:

    map 不返回 List,而是返回 SeqSeq 是一次性的 Iterable 值序列,在接收器上下文中,它将迭代其底层迭代器并丢弃生成的值。这就是为什么在接收器上下文中的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

    【讨论】:

      【解决方案2】:

      我认为这是因为只有 maplast 语句没有沉没:

      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 根本不返回List
      猜你喜欢
      • 1970-01-01
      • 2019-01-10
      • 1970-01-01
      • 2020-04-22
      • 1970-01-01
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      相关资源
      最近更新 更多