scala 为什么 Some(null) 不被认为是 None?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5796616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:58:42  来源:igfitidea点击:

Why Some(null) isn't considered None?

scalanulloption

提问by Geo

I am curious:

我好奇:

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

Why isn't Some(null)transformed to None?

为什么不Some(null)转化为None

回答by Jean-Philippe Pellet

You should use Option(null)to reach the desired effect and return None.

您应该使用Option(null)达到预期效果并返回None

Some(null)just creates a new Optionwith a defined value (hence Some) which is actually null, and there are few valid reasons to ever create one like this in real code.

Some(null)只需创建一个Option具有定义值(因此Some)的 new ,实际上是null,并且在实际代码中创建这样的值几乎没有正当理由。

回答by Daniel C. Sobral

Unfortunately, nullis a valid value for any AnyReftype -- a consequence of Scala's interoperability with Java. So a method that takes an object of type Aand, internally, store it inside an Option, might well need to store a nullinside that option.

不幸的是,null对于任何AnyRef类型都是有效值——Scala 与 Java 互操作性的结果。因此,接受类型对象A并在内部将其存储在 中的方法很Option可能需要null在该选项中存储。

For example, let's say you have a method that takes the head of a list, checks if that head correspond to a key in a store, and then return true if it is. One might implement it like this:

例如,假设您有一个方法,它获取列表的头部,检查该头部是否对应于存储中的键,如果是则返回 true。人们可能会像这样实现它:

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

So, here's the thing... if the that inside listand keyscome from some Java API, they both may well contain null! If Some(null)wasn't possible, then isFirstAcceptable(List[String](null), Set[String](null))would return falseinstead of true.

所以,这里的东西......如果这里面listkeys来自一些Java API,它们都可能包含null!如果Some(null)不可能,那么isFirstAcceptable(List[String](null), Set[String](null))将返回false而不是true.

回答by Synesso

Much of Scala's WTFs can be attributed to its need for compatibility with Java. nullis often used in Java as a value, indicating, perhaps the absence of a value. For example hashMap.get(key)will return nullif the key is not matched.

Scala 的大部分 WTF 都可以归因于它需要与 Java 兼容。null在 Java 中经常用作值,表示可能没有值。例如,如果键不匹配,hashMap.get(key)将返回null

With this in mind, consider the following possible values from wrapping a null returning method in an Option:

考虑到这一点,请考虑以下将 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)seems sufficiently distinct from Nonein this case to warrant allowing it in the language.

Some(null)None在这种情况下似乎完全不同,以保证在语言中允许它。

Of course if this is not desirable in your case then simply use:

当然,如果这在您的情况下是不可取的,那么只需使用:

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

回答by overthink

I think the others in the thread do a good job explaining why Some(null)"should" exist, but if you happen to be getting Some(null)somewhere and want a quick way to turn it into None, I've done this before:

我认为线程中的其他人很好地解释了为什么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

And when the starting Optionis a legit non-null value things work as you probably want:

当开始Option是一个合法的非空值时,事情会像你想要的那样工作:

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

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

回答by Eugene Zhulkov

Because Option is considered to be a Functor and being a Functor means:

因为 Option 被认为是一个 Functor 并且作为一个 Functor 意味着:

  1. Has unitfunction (applyor just Option("blah")in Scala)
  2. Has mapfunction which transforms value from T=>Bbut not a context
  3. Obeys 2 Functor laws - identity law and associative law
  1. 具有unit函数(apply或仅Option("blah")在 Scala 中)
  2. 具有mapT=>B上下文而不是上下文转换值的函数
  3. 遵守 2 Functor 定律 - 恒等律和结合律

In this topic the main part is #2 - Option(1).map(t=>null)can not transform context. Someshould remain. Otherwise it brakes associative law!

在本主题中,主要部分是 #2 -Option(1).map(t=>null)无法转换上下文。Some应该留下。否则它会刹车结合律!

Just consider the following laws example:

只需考虑以下法律示例:

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)

But what if Option("hello").map(t=>null)produced None? Associative law would be broken:

但是如果Option("hello").map(t=>null)生产None呢?结合律将被打破:

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

That is my thought, might be wrong

这是我的想法,可能是错误的

回答by Kevin Wright

As a simple thought experiment, consider two lists of Strings, one of length 5 and one of length 20.

作为一个简单的思想实验,考虑两个字符串列表,一个长度为 5,一个长度为 20。

Because we're running on the JVM, it's possible to insert nullas a valid element into one of these lists - so put that in the long list as element #10

因为我们在 JVM 上运行,所以可以将null一个有效元素作为有效元素插入到这些列表之一中 - 所以将它作为元素 #10 放在长列表中

What, then, should the difference be in the values returned from the two following expressions?

那么,从以下两个表达式返回的值应该有什么区别?

EDIT:Exchanged getfor lift, I was thinking of maps...

编辑:交换getlift,我在考虑地图...

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