Подтвердить что ты не робот

Почему Some (null) не считается None?

Мне любопытно:

scala> Some(null) == None
res10: Boolean = false

Почему Some(null) не преобразован в None?

4b9b3361

Ответ 1

Вы должны использовать Option(null) для достижения желаемого эффекта и возврата None.

Some(null) просто создает новый Option с определенным значением (следовательно, Some), который на самом деле null, и есть несколько веских причин когда-либо создавать такой код в реальном коде.

Ответ 2

К сожалению, null - допустимое значение для любого типа AnyRef - следствие взаимодействия Scala с Java. Таким образом, метод, который принимает объект типа A и внутренне хранящий его внутри Option, вполне может потребоваться сохранить null внутри этой опции.

Например, скажем, у вас есть метод, который берет начало списка, проверяет, соответствует ли эта глава ключу в хранилище, а затем возвращает true, если это так. Можно реализовать его так:

def isFirstAcceptable(list: List[String], keys: Set[String]): Boolean =
    list.headOption map keys getOrElse false

Итак, вот что... если внутри list и keys исходит какой-то Java API, они оба могут содержать null! Если Some(null) невозможно, то isFirstAcceptable(List[String](null), Set[String](null)) вернет false вместо true.

Ответ 3

Большая часть Scala WTFs может быть отнесена к его потребности в совместимости с Java. null часто используется в Java как значение, указывающее, возможно, отсутствие значения. Например, hashMap.get(key) вернет null, если ключ не соответствует.

С учетом этого рассмотрим следующие возможные значения обертывания нулевого метода возврата в Option:

if (b) Some(hashMap.get(key)) else None
// becomes -->
None // the method was not invoked;
Some(value) // the method was invoked and a value returned; or
Some(null) // the method was invoked and null was returned.

Some(null) кажется достаточно отличным от None в этом случае, чтобы гарантировать его на языке.

Конечно, если это нежелательно в вашем случае, просто используйте:

if (b) Option(hashMap.get(key)) else None
// becomes -->
None // the method was not invoked or the mapped value was null; or
Some(value) // the method was invoked and a value returned

Ответ 4

Я думаю, что другие в потоке хорошо справляются, объясняя, почему Some(null) "должно" существовать, но если вы когда-нибудь получаете Some(null) и хотите быстрый способ превратить его в None, я ' вы сделали это раньше:

scala> val x: Option[String] = Some(null)
x: Option[String] = Some(null)

scala> x.flatMap(Option(_))
res8: Option[String] = None

И когда начальный Option является законным значением, отличным от нуля, все работает так, как вы, вероятно, хотите:

scala> val y: Option[String] = Some("asdf")
y: Option[String] = Some(asdf)

scala> y.flatMap(Option(_))
res9: Option[String] = Some(asdf)

Ответ 5

В качестве простого мысленного эксперимента рассмотрим два списка строк, один из которых длиной 5 и один длиной 20.

Поскольку мы работаем на JVM, можно вставить null в качестве допустимого элемента в один из этих списков - поэтому поставьте это в длинном списке как элемент # 10

В чем же разница в значениях, возвращаемых из двух следующих выражений?

EDIT: Обмен get для lift, я думал о картах...

shortList.lift(10) //this element doesn't exist
longList.lift(10)  //this element exists, and contains null

Ответ 6

Поскольку Опция считается Функтором и является Функтором, значит:

  • Функция unit (apply или просто Option("blah") в Scala)
  • Функция map, которая преобразует значение из T=>B, но не контекст
  • Повинуется 2 Законы-функторы - закон тождественности и ассоциативный закон

В этом разделе основная часть # 2 - Option(1).map(t=>null) не может преобразовать контекст. Some должен оставаться. В противном случае он тормозит ассоциативный закон!

Просто рассмотрите пример следующих законов:

def identity[T](v: T) = v
def f1(v: String) = v.toUpperCase
def f2(v: String) = v + v
def fNull(v: String): String = null

val opt = Option("hello")

//identity law
opt.map(identity) == opt //Some(hello) == Some(hello)

//associative law
opt.map(f1 _ andThen f2) == opt.map(f1).map(f2) //Some(HELLOHELLO) == Some(HELLOHELLO)
opt.map(fNull _ andThen f2) == opt.map(fNull).map(f2) //Some(nullnull) == Some(nullnull)

Но что, если Option("hello").map(t=>null) произвело None? Ассоциативный закон будет нарушен:

opt.map(fNull _ andThen f2) == opt.map(fNull).map(f2) //Some(nullnull) != None

Это моя мысль, может быть неправильно