【问题标题】:“Convert” Option[x] to x in Scala在 Scala 中将 Option[x] 转换为 x
【发布时间】:2013-11-14 22:52:24
【问题描述】:

我正在使用 scala (2.1) 的游戏,我需要将“Option[Long]”值转换为“Long”。

我知道如何反其道而行之,我的意思是:

  def toOption[Long](value: Long): Option[Long] = if (value == null) None else Some(value)

但就我而言,我必须将“Option[Long]”的值作为类型传递给采用“Long”的方法。 请提供任何帮助。

【问题讨论】:

    标签: scala casting playframework type-conversion options


    【解决方案1】:

    如果你有 x 作为 Option[Long],x.get 会给你 Long。

    【讨论】:

    • 这个答案是错误的。如果 x 是None(可能是Option[Long]),调用get 会抛出错误。
    • 我们可以使用 x.getOrElse(None)
    • 是的,更好的选择是使用 x.getOrElse()
    • 这怎么比接受的答案有更多的赞成票,这到底是什么?这个答案太有害了。有关详细信息,请参阅github.com/alexandru/scala-best-practices/blob/master/sections/…。我建议直接删除这个答案。
    【解决方案2】:

    首先,您对“相反”的实施存在一些严重问题。通过在方法上放置一个名为 Long 的类型参数,您可以从标准库中隐藏 Long 类型。您可能指的是以下内容:

    def toOption(value: Long): Option[Long] =
      if (value == null) None else Some(value)
    

    即使这有点荒谬(因为scala.Long 不是引用类型,也不能是null),除非你指的是java.lang.Long,这是一个痛苦和混乱的秘诀。最后,即使您正在处理引用类型(如String),您最好编写以下内容,这是完全等价的:

    def toOption(value: String): Option[String] = Option(value)
    

    当且仅当valuenull 时,此方法才会返回None

    为了解决您的问题,假设我们有以下方法:

    def foo(x: Long) = x * 2
    

    您通常不应该考虑将Option[Long] 传递给foo,而是通过mapfoo“提升”到Option

    scala> val x: Option[Long] = Some(100L)
    x: Option[Long] = Some(100)
    
    scala> x map foo
    res14: Option[Long] = Some(200)
    

    Option 的全部意义在于模拟(在类型级别)“空”值的可能性,以避免整个类的NullPointerException-y 问题。在Option 上使用map 允许您对Option 中可能存在的值执行计算,同时继续对它为空的可能性进行建模。

    作为另一个答案,也可以使用getOrElse 来“拯救”Option,但这通常不是 Scala 中的惯用方法(除非确实存在合理的默认值)。

    【讨论】:

    • 如果它是一个我们需要很长的实现请求,getOrElse 是唯一的方法吗?
    【解决方案3】:

    此方法已在 Option[A] 上定义并称为 get

    scala> val x = Some(99L)
    x: Some[Long] = Some(99)
    
    scala> x.get
    res0: Long = 99
    

    问题是在 None 上调用 get 会抛出 NoSucheElement 异常:

    scala> None.get
    java.util.NoSuchElementException: None.get
    

    因此,您不会从使用 Option 类型中获得任何好处。

    如前所述,如果您可以提供合理的默认值或处理异常,则可以使用 getOrElse

    惯用的 scala 方式是使用 map 或 for-comprehension

    x map (_ + 1)
    res2: Option[Long] = Some(100)
    

    for (i <- x) yield i +1
    res3: Option[Long] = Some(100)
    

    【讨论】:

      【解决方案4】:

      选项是本地化副作用的方法(您的函数可以返回空值)。以及将计算提升到 Option 的良好风格(Option 是 Monad,带有 mapflatMap 方法)。 p>

      val x = Option[Long](10) 
      x.map { a => a + 10 }
      

      并通过手动处理副作用提取值:

      val res = x match {
        case Some(a) => s"Value: $a"
        case None    => "no value"
      } 
      

      【讨论】:

        【解决方案5】:

        You need to decide what happens when the option is None.是否提供默认值?

        def unroll(opt: Option[Long]): Long = opt getOrElse -1L  // -1 if undefined
        
        unroll(None) // -> -1
        

        你也可以抛出异常:

        def unroll(opt: Option[Long]): Long = opt.getOrElse(throw 
          new IllegalArgumentException("The option is expected to be defined at this point")
        )
        
        unroll(None) // -> exception
        

        以防万一,请不要使用null,除非您有充分的理由使用它 (opt.orNull)。

        【讨论】:

          【解决方案6】:

          正如已经提到的,getOrElse 可能是您在直接回答问题时所寻找的。​​p>

          另请注意,要转换为选项,您只需:

          val myOption = Option(1)
          

          myOption 现在将是 Some(1)

          val myOption = Option(null)
          

          myOption 现在将为 None。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-06-11
            • 2020-06-18
            • 2010-12-26
            • 1970-01-01
            • 2016-04-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多