Обертывание метода с возвратом нуля в Java с помощью Option в Scala?

107

Предположим, у меня есть метод, session.get(str: String): Stringно вы не знаете, вернет ли он вам строку или ноль, потому что он исходит из Java.

Есть ли более простой способ решить эту проблему в Scala вместо session.get("foo") == null? Может быть, применима какая-то магия, ToOption(session.get("foo"))и тогда я могу рассматривать ее в Scala как

ToOption(session.get("foo")) match {
    case Some(_) =>;
    case None =>;
}
Хосе Леаль
источник
4
Дополнительные сведения о трюках с опциями
Landei
4
Ссылка выше должна быть blog.tmorris.net/posts/scalaoption-cheat-sheet .
Яцек Ласковски

Ответы:

182

Метод Optionсопутствующего объекта applyслужит функцией преобразования из ссылок, допускающих значение NULL:

scala> Option(null)
res4: Option[Null] = None

scala> Option(3)   
res5: Option[Int] = Some(3)
Том Крокетт
источник
19

У Optionобъекта есть applyметод, который делает именно это:

var myOptionalString = Option(session.get("foo"));
RoToRa
источник
5

Обратите внимание, что при работе с объектами Java это не работает должным образом:

val nullValueInteger : java.lang.Integer = null
val option: Option[Int] = Option(nullValueInteger)
println(option)  // Doesn't work - zero value on conversion

val nullStringValue : String = null
val optionString: Option[String] = Option(nullStringValue)
println(optionString) // Works - None value
ДекельМ
источник
1
Я работал со scala 2.11.8. Вторая строка выбросила исключение NullPointerException. В шестой строке было Some (null), а не None, как вы ожидали.
Джон Линь
1. Использовал Some вместо Option в optionString - изменен в исходном ответе. 2. Проверено только в Scala 2.12.5
DekelM
-3

Это очень старая тема, но хорошая!

Это правда, что преобразование любого результата попытки без исключения в вариант приведет к некоторому ...

scala> Try(null).toOption
res10: Option[Null] = Some(null)

... потому что Try - это не проверка допустимости значений NULL, а просто способ функциональной обработки исключений.

Использование Try для перехвата исключения и преобразование его в Option для удобства покажет None только в случае возникновения исключения.

scala> Try(1/0).toOption
res11: Option[Int] = None

Вы хотите сохранить ценности, полученные с помощью Try. Это может быть пустым.

Но верно также и то, что стандартная библиотека иногда довольно сбивает с толку ...

scala> Try(null).toOption
res12: Option[Null] = Some(null)

scala> Option(null)
res13: Option[Null] = None

Такое поведение немного непоследовательно, но отчасти отражает намеренное использование как Try, так и Option.

Вы используете try, чтобы получить все, что выходит из выражения, которое может вызывать исключения, и вас не волнует само исключение.

Значение, которое может получиться, вполне может быть нулевым. Если toOption предоставил None, вы не сможете отличить исключение от нуля , и это некрасиво!

В автономном режиме вы используете Option, чтобы инкапсулировать существование чего-либо. Итак, в этом случае Some (null) равен None, и это имеет смысл, потому что null в этом случае представляет собой отсутствие чего-либо. Здесь нет двусмысленности.

Важно отметить, что в любом случае ссылочная прозрачность не нарушается, поскольку .toOption не то же самое, что Option ()

Если вам действительно необходимо для обеспечения ОБА безопасности исключения и нулевой безопасности, и ваш код действительно действительно не нужен differenciate между нулем и исключением , вам просто нужно объединить обе парадигмы! Потому что это то, чего ты хочешь, правда?

Вы можете сделать это одним способом ...

scala> Try(Option(null)).getOrElse(None)
res23: Option[Null] = None

scala> Try(Option(3/0)).getOrElse(None)
res24: Option[Int] = None

scala> Try(Option(3)).getOrElse(None)
res25: Option[Int] = Some(3)

... или другой ...

scala> Try(Option(null)).toOption.flatten
res26: Option[Null] = None

scala> Try(Option(3/0)).toOption.flatten
res27: Option[Int] = None

scala> Try(Option(3)).toOption.flatten
res28: Option[Int] = Some(3)

... или до смехотворно уродливого из них другие ...

scala> Option(Try(null).getOrElse(null))
res29: Option[Null] = None

scala> Option(Try(3/0).getOrElse(null))
res30: Option[Any] = None

scala> Option(Try(3).getOrElse(null))
res31: Option[Any] = Some(3)
Дэвид Ройо
источник