Новое поведение в Scala 2.10

Вот два сеанса REPL (вдохновленные этим вопросом , хотя мой вопрос отличается):

Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def ignore(it: String) = 42
ignore: (it: String)Int

scala> ignore(null.asInstanceOf[Nothing])
res0: Int = 42

А также:

Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def ignore(it: String) = 42
ignore: (it: String)Int

scala> ignore(null.asInstanceOf[Nothing])
java.lang.NullPointerException
        at .(:9)
        at .()
        at .(:7)
        at .()
        at $print()
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...

Единственное отличие состоит в том, что первая - Scala 2.9.2, а вторая - 2.10.0.

Может ли кто-нибудь указать на изменения в 2.10, которые приводят к этому новому поведению?

Я знаю, что приведение к Nothing - это глупое дело, и что ответ может быть «это все неопределенное поведение, поэтому просто прекратите это делать», но это похоже на то, что может потенциально имеют последствия для обновителей, и я не помню, чтобы участвовать в каких-либо обсуждениях изменений, которые могли бы объяснить это.

10
nl ja de
Поскольку 2.10 еще не стабилен, вероятно, это хорошая идея перечислить это как ошибку. Если это не так, это должно быть документировано. Если это так, оно должно быть исправлено до 2.10final
добавлено автор Martijn, источник

3 ответы

Поскольку Scala рассматривает null по-разному от случая None для параметра, даже значение null Nothing является проблематичным - - должны быть ровно нулевые экземпляры Nothing , а не один экземпляр, который может или не может сломаться в зависимости от того, как вы его используете.

Таким образом, я не вижу, как старое поведение - это всего лишь ошибка. В примечаниях к выпуску следует отметить, что он был исправлен, но полагаясь на .asInstanceOf [Nothing] , чтобы сделать что-либо сохранить выброс исключения, достаточно противоречит типу, Я не думаю, что больше ничего не нужно. (На самом деле, я даже не думаю, что примечание к выпуску необходимо.)

5
добавлено

Это выглядит как проблема только с консолью, а не с языком. Если вы запустите это небольшое приложение, которое вызывает тот же самый метод, у scala 2.10 нет проблем с ним.

object Test extends App {
  override def main(args: Array[String]) {
    println(takesString(null.asInstanceOf[Nothing]))
  }

  def takesString(a: String) = 42
}

Чтобы упростить свой пример сверху, вы можете просто ввести

null.asInstanceOf[Nothing]

and the console would give you the same error. I presume it has something to do with printing out the type.

Update: Looks like I accidentally ran against 2.9.2. Still fails as a script in 2.10 RC5 as the author points out in comment.

3
добавлено
Спасибо, но я действительно попробовал это (или что-то подобное, так или иначе), и видел то же поведение, что и в REPL. Я также просто попробовал компиляцию и запуск вашего кода и получить ошибку времени выполнения с помощью 2.10.0 (но не 2.9.2). Какую версию 2.10.0 вы используете?
добавлено автор Travis Brown, источник

Я знаю, что вы не ожидаете ответа «это все неопределенное поведение, поэтому (...)», но когда вы добавляете «вещь, которая потенциально может иметь последствия для обновлений», я должен помнить (даже если это очевидно), что люди < strong> не может полагаться или ожидать чего-либо результата вещи, которая имеет неопределенное поведение, своим собственным определением.

В конкретном случае, о котором вы говорили, я не думаю, что это неопределенное поведение: оно должно вызывать исключение. Nothing является подклассом Null , а не наоборот - мое первое ожидание без тестирования заключалось в том, что строка null.asInstanceOf [Nothing] будет генерировать ClassCastException , поскольку null не является Nothing . Однако вы можете видеть, что null - это специальный экземпляр (как в Java). Попробуйте запустить:

scala> "aaa".asInstanceOf[Nothing]
java.lang.ClassCastException: java.lang.String cannot be cast to scala.runtime.N
othing$
        at .(:8)
        at .()

Я предполагаю, что это происходит потому, что внутри, obj.asInstanceOf [T] вызывает obj.getClass() , чтобы проверить приведение во время выполнения. Как вызов любого метода в null выдает NullPointerException , это исключение генерируется перед ClassCastException .

Вернемся к вашему конкретному вопросу, кажется, что Scala 2.9.2 обрабатывает особым образом особый случай. Выполнение еще нескольких тестов:

scala> ignore(3.asInstanceOf[String])
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stri
ng
        at .(:9)
        at .()
scala> ignore({ println("test"); "aaa" })
test
res6: Int = 42

Вы можете видеть, что аргумент всегда оценивается, кроме вашего случая. Scala 2.10 определенно имеет наиболее последовательное поведение. Однако эта проблема не должна влиять на обновление разработчика до Scala 2.10; Я не вижу никакого случая, когда obj.asInstanceOf [Nothing] - правильный код.

2
добавлено
pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

Scala User Group
Scala User Group
1 486 участник(ов)

[RU] Scala Chat. Rules, additional links, FAQ: https://telegra.ph/Russian-Speaking-Scala-User-Group-08-27

Scala Jobs
Scala Jobs
852 участник(ов)

Rules: http://telegra.ph/My-lyudi-i-ehto-znachit-chto-nam-nuzhna-organizaciya-02-07 Main Scala Channel: https://t.me/scala_jobs_feed Flood Room: https://t.me/scala_ponv