Почему Flatten на вложенном Iterator не компилируется и зачем мне присвоение типа?

(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

2 ответа

Решение

Я считаю, что эта проблема была решена путем включения частей составного / уточняющего типа в неявную область видимости. #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 flatten на Iteratorбыл предоставлен как метод расширения через flattenTraversable, как только проблема возникнет для анонимногоIterator учебный класс.


Вот мой ответ до редактирования выше:

Похоже, это как-то связано с неявным разрешением как в 2.11, так и в 2.12. Если вы явно импортируетеflatten как метод расширения через

import scala.collection.TraversableOnce.flattenTraversableOnce

тогда вроде работает. Проблема, кажется, исправлена ​​начиная с версии 2.13.0-M3, где фаза ввода дает

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.

. набирается так, как если бы это было { val =; . }

Я думаю, он пытается это разобрать:

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

как это

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

Обратите внимание, где я добавил круглые скобки ().

Другие вопросы по тегам