【问题标题】:Why does flatten on nested Iterator not compile and why do I need type ascription?为什么嵌套迭代器上的展平无法编译,为什么我需要类型归属?
【发布时间】:2026-01-05 12:50:02
【问题描述】:
(new Iterator[List[Int]] {
  def hasNext: Boolean = ???
  def next(): List[Int] = ???
}).flatten

给出错误:

value flatten is not a member of Iterator[List[Int]]
[error] possible cause: maybe a semicolon is missing before `value flatten'?
[error]     }.flatten
[error]       ^
[error] one error found

但是

(new Iterator[List[Int]] {
  def hasNext: Boolean = ???
  def next(): List[Int] = ???
}: Iterator[List[Int]]).flatten

有效。也可以将迭代器存储在 val 中。

Scala 版本:2.11.8

【问题讨论】:

    标签: scala type-inference ascription


    【解决方案1】:

    我相信Include the parts of a compound/refinement type in implicit scope. #5867 已经解决了这个问题。问题是伴随匿名类过去不符合隐式搜索的条件

    我认为 aaf9198#diff-7c03397456d3b987549fd039d6b639c6R516 是 首先排除细化/匿名类 同伴隐含。 @odersky 你还记得动机吗?

    这是一个最小的复制

    trait A {
      def foo(): Int
    }
    class B {
      def bar(): String = "woohoo"
    }
    object A {
      implicit def aToB(a: A): B = new B
    }
    
    (new A {
      override def foo(): Int = 42
    }).bar()
    
    // Error: 
    // value bar is not a member of A$A12.this.A 
    // possible cause: maybe a semicolon is missing before `value bar'? }).bar();
    

    因此,由于在 2.11 和 2.12 中,Iterator 上的 flatten 是通过 flattenTraversableOnce 作为扩展方法提供的,因此该问题将针对匿名 Iterator 类出现。


    以下是我在上述编辑之前的回答:

    这似乎与 2.11 和 2.12 中的隐式解析有关。如果您通过

    显式导入flatten作为扩展方法
    import scala.collection.TraversableOnce.flattenTraversableOnce
    

    然后它似乎工作。自 2.13.0-M3 以来,该问题似乎已得到解决,其中 typer 阶段给出了

    collection.this.TraversableOnce.flattenTraversableOnce[Int, List]({
      final class $anon extends AnyRef with Iterator[List[Int]] {
        def <init>(): <$anon: Iterator[List[Int]]> = {
          $anon.super.<init>();
          ()
        };
        def hasNext: Boolean = scala.Predef.???;
        def next(): List[Int] = scala.Predef.???
      };
      new $anon()
    })(scala.Predef.$conforms[List[Int]]).flatten
    
    

    虽然在 2.13.0 版本中 flatten 似乎不再通过扩展方法提供

    {
      final class $anon extends AnyRef with Iterator[List[Int]] {
        def <init>(): <$anon: Iterator[List[Int]]> = {
          $anon.super.<init>();
          ()
        };
        def hasNext: Boolean = scala.Predef.???;
        def next(): List[Int] = scala.Predef.???
      };
      new $anon()
    }.flatten[Int](scala.Predef.$conforms[List[Int]])
    

    上面的展开好像是SLS 6.4 Designators解释的

    ?.? 的输入就像是 { val ? = ?; ?.? }

    【讨论】:

      【解决方案2】:

      我认为它试图解析这个:

      new Iterator[List[Int]] {
            def hasNext: Boolean = ???
            def next(): List[Int] = ???
          }.flatten
      

      这样

      new Iterator[List[Int]] ( {
            def hasNext: Boolean = ???
            def next(): List[Int] = ???
          }.flatten )
      

      注意我在哪里添加了括号 ()

      【讨论】:

      • 在整个迭代器周围添加参数会得到相同的结果(编辑过的 OP)。
      最近更新 更多