【问题标题】:Why Some(null) isn't considered None?为什么 Some(null) 不被视为无?
【发布时间】:2011-08-13 09:19:09
【问题描述】:

我很好奇:

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

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

【问题讨论】:

    标签: scala null option


    【解决方案1】:

    你应该使用Option(null)来达到想要的效果并返回None

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

    【讨论】:

    • 这并不能解释太多......你能更明确一点吗?
    • @Mauricio Daniel 有一个很好的例子说明为什么不应将 Some(null) 转换为 None
    【解决方案2】:

    不幸的是,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,那么它们很可能都包含null!如果Some(null) 不可能,那么isFirstAcceptable(List[String](null), Set[String](null)) 将返回false 而不是true

    【讨论】:

    • @Jean-PhilippePellet null 在 Scala 中根本不应该存在,并且每个 Java 到 Scala 的接口都需要将 Java 类型包装在 Option 中。 (这实际上是一些没有null 的语言,例如Rust,如何提供与具有null 的语言的互操作。)
    【解决方案3】:

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

    【讨论】:

    • 确实“为什么”很有趣,但我们大多数人可能更像是“下一步该做什么”。非常感谢。
    【解决方案4】:

    Scala 的许多 WTF 可以归因于它需要与 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
    

    【讨论】:

    • “Scala 的许多 WTF 可以归因于它需要与 Java 兼容”... 在 java 中只有一个 Optional.EMPTY 实例。如果您有一个与 Optional.EMPTY 具有不同标识的可选项,则可以保证它不会被 null 包装。正如你所说,这个 WTF 在 Java 中不存在,但在 Scala 中存在。
    • 没有很多事情比三个状态布尔值更糟糕。
    【解决方案5】:

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

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

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

    编辑:get 换成lift,我在考虑地图...

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

    【讨论】:

    • 前者抛出IndexOutOfBoundsException
    • @Synesso - shortList(10) 会抛出异常,真的。但这不是我正在做的......
    • 抱歉,我以为您在谈论 java.util.List,因为您的论点似乎与我的相似。我假设太多了!
    • @Synesso - 啊,好吧,使用 Java 的列表会带来一系列完全不同的问题,而且是非常不明智的!
    【解决方案6】:

    因为 Option 被认为是 Functor,而成为 Functor 意味着:

    1. 具有unit 函数(apply 或仅在 Scala 中为 Option("blah")
    2. 具有 map 函数,可将值从 T=>B 转换为上下文,但不是上下文
    3. 遵守 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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-20
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      相关资源
      最近更新 更多