Почему карта / фильтр ... не работает с массивом ничего? - PullRequest
3 голосов
/ 30 апреля 2011

Разве Ничто не является подтипом всех типов?

scala> val array = new Array(5)
array: Array[Nothing] = Array(null, null, null, null, null)

scala> array.map(_ => 42)
<console>:9: error: value map is not a member of Array[Nothing]
       array.map(_ => 42)
             ^

scala> array.filter(_ != 42)
<console>:9: error: value filter is not a member of Array[Nothing]
       array.filter(_ != 42)
             ^

Странно, что это не работает.

Указано ли это, функция или ошибка?

Ответы [ 3 ]

7 голосов
/ 01 мая 2011

Когда вы видите странное поведение, связанное с Nothing, это происходит потому, что алгоритм вывода типов думает, что он сам вставил Nothing, поскольку он вводится во время вывода типов: если ничего не известно о переменной типа, тогда он ограничен Any и Nothing.Уже давно в моем списке вещей, чтобы посмотреть, смогу ли я ввести для этой цели новый нижний тип, предназначенный только для внутреннего использования, поэтому ничего на уровне пользователя и на уровне вывода ничего не смешиваются, но это довольно амбициозная задача.Тем не менее, теперь я могу быть достаточно хардкорным, чтобы попробовать это.

4 голосов
/ 30 апреля 2011

Обратите внимание, что тип массива Scala является инвариантным. Так что Nothing как подтип всего может не относиться к делу.

Также map и filter не определены в Array. Неявные преобразования в Predef используются для предоставления таких методов для массивов.

Таким образом, компилятор не может найти неявное преобразование из Array[Nothing] во что-то, для чего определены map или filter. Используя REPL, я действительно вижу, что такое неявное преобразование должно быть доступно:

scala> val conv = implicitly[Array[Nothing] <%< collection.mutable.ArrayOps[Nothing]]

conv: <%<[Array[Nothing],scala.collection.mutable.ArrayOps[Nothing]] = <function1>

scala> conv(new Array[Nothing](5)).filter(_ => true)
res8: Array[Nothing] = Array(null, null, null, null, null)

Таким образом, возникает вопрос, почему компилятор не учитывает преобразование genericArrayOps.

4 голосов
/ 30 апреля 2011

Я подозреваю, что Скала не должен позволять вам делать такие Array[Nothing] экземпляры. По определению нет никаких экземпляров ничего вокруг, но ваш массив выглядит так, как будто он заполнен Nothing s, которые имеют значение null, но null не является допустимым значением для Nothing. Это, например, происходит с ошибкой type mismatch; found : Null(null) required: Nothing

val n: Nothing = null

Так что я ожидал бы столкнуться с неприятностями каждый раз, когда вы действительно можете обмануть систему, полагая, что вы наконец-то овладели столь востребованным, например, Nothing

Вот еще один странный случай. Запустите это:

object Main {

  class Parametrized[T] { var value: T = _ }

  def main(args: Array[String]) {
    val p = new Parametrized // typed as Parametrized[Nothing]
    val n = p.value  // n is now actually an instance of Nothing... isn't it?
    println(p.value) // prints null, but null is not an instance of Nothing
    println(n)       // throws NullPointerException...
  }

}
...