Каков фактический тип возвращаемого значения метода filter для диапазона? Как мне сделать это вектором?

#scala

#scala

Вопрос:

Я совершенно новичок в Scala, так что потерпите меня, пожалуйста! Я выполняю несколько упражнений Scala, и одно из них заключается в создании списка нечетных чисел от 1 до 20. Это довольно прямолинейно, но меня немного смущает тип возвращаемого значения filter метода для диапазона.

У меня есть следующий блок:

 val lst2 = (1 to 20).filter(_ % 2 != 0)
println(lst2)
  

Результатом этого является:

Вектор(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)

Однако, когда я явно задаю тип lst2 на Vector[Int] , подобный следующему:

 val lst2: Vector[Int] = (1 to 20).filter(_ % 2 != 0)
println(lst2)
  

Я получаю это:

16: ошибка: несоответствие типов;

найдено: scala.collection.immutable.IndexedSeq[Int]

требуется: Vector[Int] val lst2: Vector[Int] = (от 1 до 20).filter(_ % 2 != 0) ^ найдена одна ошибка

Итак, в чем тут дело? println Метод просто не выдает мне правильный тип? Как мне заставить метод filter возвращать вектор?

Ответ №1:

Единственная гарантия, предоставляемая filter of Range , заключается в том, что он возвращает collection.immutable.IndexedSeq[A] , поэтому это компилирует:

 val lst2: collection.immutable.IndexedSeq[Int] = (1 to 20).filter(_ % 2 == 1)
  

Во время выполнения lst2 просто получается a Vector[Int] , но это не гарантируется интерфейсом, поэтому авторы filter метода фактически оставляют за собой право изменять конкретную реализацию на другую IndexedSeq , когда им заблагорассудится. Тип Vector — это деталь реализации, на которую вам не следует полагаться.

Причина, по которой он печатается как Vector(...) , заключается в том, что это зависит от реализации toString конкретного экземпляра, который присутствует во время выполнения, а не от статически известного типа (динамическая отправка).

Если вы действительно хотите что-то с типом Vector , просто добавьте .toVector :

 val lst2: Vector[Int] = (0 to 20).filter(_ % 2 == 1).toVector