Почему 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 )
Обратите внимание, где я добавил круглые скобки ()
.