为什么 Some(null) 不被视为 None?

发布于 2024-11-03 11:51:05 字数 150 浏览 9 评论 0原文

我很好奇:

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

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

I am curious:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

独夜无伴 2024-11-10 11:51:05

您应该使用Option(null)来达到所需的效果并返回None

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

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

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

第几種人 2024-11-10 11:51:05

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

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

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

所以,事情是这样的...如果 listkeys 中的内容来自某个 Java API,它们很可能都包含 空!如果 Some(null) 不可能,则 isFirstAcceptable(List[String](null), Set[String](null)) 将返回 false< /code> 而不是 true

Unfortunately, null is a valid value for any AnyRef type -- a consequence of Scala's interoperability with Java. So a method that takes an object of type A and, internally, store it inside an Option, might well need to store a null inside that option.

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:

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

So, here's the thing... if the that inside list and keys come 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 false instead of true.

金兰素衣 2024-11-10 11:51:05

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

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:

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

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

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

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

scala> y.flatMap(Option(_))
res9: Option[String] = Some(asdf)
榆西 2024-11-10 11:51:05

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

考虑到这一点,请考虑将 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

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

With this in mind, consider the following possible values from wrapping a null returning method in an 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 None in this case to warrant allowing it in the language.

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
你又不是我 2024-11-10 11:51:05

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

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

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

编辑:get交换为lift,我正在考虑地图......

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

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

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

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

EDIT: Exchanged get for lift, I was thinking of maps...

shortList.lift(10) //this element doesn't exist
longList.lift(10)  //this element exists, and contains null
煞人兵器 2024-11-10 11:51:05

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

  1. 在 Scala 中具有 unit 函数(apply 或只是 Option("blah") )
  2. 具有 map 函数,可从 T=>B 转换值,但不遵循上下文
  3. 遵守 2 个函子法则 - 恒等法则和结合法则

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

只需考虑以下定律示例:

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

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

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

  1. Has unit function (apply or just Option("blah") in Scala)
  2. Has map function which transforms value from T=>B but not a context
  3. Obeys 2 Functor laws - identity law and associative law

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

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:

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

That is my thought, might be wrong

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文