为什么扁平化嵌套迭代器无法编译,为什么我需要类型归属?

Why does flatten on nested Iterator not compile and why do I need type ascription?

(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

我认为它试图解析这个:

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

这样

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

请注意我在何处添加了括号 ()

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

I think aaf9198#diff-7c03397456d3b987549fd039d6b639c6R516 was the first to exclude refinement/anon classes from contributing to companion implicits. @odersky Can you remember the motivation?

这里是最小复制

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 class .


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

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

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

然后它似乎工作。这个问题似乎从 2.13.0-M3 开始得到解决,其中 typer phase gives

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

来解释

. is typed as if it was { val = ; . }