2015-12-18 2 views
6

Должно ли Success (ребенок от Try) вернуть Some(null) при преобразовании его в Option?Scala Метод try toOption возвращает Некоторый (null)

E.g. Try(null).toOption in scala 2.11.7 возвращает Some(null) Метод успеха toOption реализован просто путем возврата Some(value). Почему он не возвращает None при преобразовании Try в опцию с использованием метода toOption, если базовое значение try равно null?

+7

'null' является допустимым (хотя и опасным) значением, поэтому' toOption' должен его сохранить. Преобразование 'Try' в' Option' отбрасывает ошибку, а не значение. – Lee

+2

... еще 'Option (null)' is 'None' делает его несколько запутанным –

+2

Как' Option (null) 'производит' None' 'toOption' в любом классе, который должен вести себя аналогичным образом, IMHO – maks

ответ

4

Вот источник toOption от Scala 2.11.7:

def toOption: Option[T] = if (isSuccess) Some(get) else None 

Я согласен с Бруно, что это сбивает с толку, он, вероятно, следует прочитать

def toOption: Option[T] = if (isSuccess) Option(get) else None 
+2

Возврат null путают. Ваше предположение предполагает, что значение null неотличимо от отказа. Легче просто «toOption.filter (_! = Null)», или если вы это делаете часто, возможно, использование Java-API делает его методом расширения. –

0

Абсолютно нет. Опция НЕ является контейнером с нулевой безопасностью, это Functor, Monad и Collection размером 0 или 1. Он может содержать нуль, как и List. Точно так же, как Try.

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

Кроме того, язык не позволяет определить тип параметра, который не является нулевым, так Try[A] неявно говорят, что А может быть пустым, в зависимости от языка, и Option[A] означает, что значение может быть пустым, тоже. Только по соглашению А обычно не является нулевым.

Было бы неверно преобразовать Try, содержащее нулевое значение, в None, так как это будет усекать диапазон A неявно. Some[A](null) действителен, для любого A, который является AnyRef

Дизайн языка не соответствует его собственным лучшим практикам. Этот язык делает практически ничего, чтобы обеспечить его соблюдение. Null является допустимым нижним типом. Идеальный мир позволил бы пользователям определять типы, не подлежащие обнулению, и компилятор для отслеживания нулевого введения и устранения, что устранило бы подобные сюрпризы.

Обратите внимание, что если мы сделали toOption конвертировано нулевые значения на None, то равенство будет не занимать:

val t: Try = ... 
t.toOption.map(f) == t.map(f).toOption 

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

Для этого в Scala должно быть два типа: один из которых является нулевым контейнером безопасности (Maybe?) И нарушает закон выше, в общем, потому что он не может содержать нуль, а другой, как и сегодняшний вариант, но без Option.apply - необязательное значение.

Option.apply - это странный человек, и его следует удалить, ИМО.

Для примера рассмотрим следующий, все из которых вычисляться Some(null):

Some(Some(null)).flatten 
List("a", null).find(s != "a") 
List(null, "blah").headOption 
Try(null).toOption 

Опция используется во всей библиотеке коллекций быть коллекция размера 0 или 1, и не нулевое предохранительное устройство. Для них нет смысла возвращать None до тех пор, пока Option является в первую очередь коллекцией размером 0 или 1, а не «ненулевой» оболочкой. Если опция была такой, то она не будет использоваться в библиотеке коллекций для представления необязательных значений, например, с find и headOption выше.

Если кто-то действительно хочет, чтобы попасть в сорняки на эту тему, весело: https://groups.google.com/forum/#!msg/scala-internals/1DXdknjt9pY/_moEcbNd4noJ

5 лет назад я думал, что это отличная идея, чтобы избавиться от Some(null). Теперь я бы предложил избавиться от Option.apply и создать другой тип для ненулевого значения. Назовите его Maybe. Тогда можно было бы Try.toMaybe вдоль стороны Try.toOption

+0

Не мое мнение. Зная, что Option (null) дает вам None, вы можете просто ожидать Try ({null)). ToOption тоже не будет. Как сказано выше в комментариях, хвост не должен вилять собакой. –

+0

@GerhardHagerer Этот аргумент разваливается перед лицом таких вещей, как List (null, «blah»). HeadOption - Знание того, что Option (null) дает вам None, вы ожидали бы None в результате? НЕТ! Опция представляет собой, прежде всего, коллекцию размером 0 или 1. Опция this.apply является исключением. –

Смежные вопросы