在 Scala 中将 Option[x] 转换为 x

Posted

技术标签:

【中文标题】在 Scala 中将 Option[x] 转换为 x【英文标题】:“Convert” Option[x] to x in Scala 【发布时间】: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”的方法。 请提供任何帮助。

【问题讨论】:

【参考方案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。

【讨论】:

以上是关于在 Scala 中将 Option[x] 转换为 x的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在Scala反射中将字符串转换为类型?

在 Scala 中将 BIGINT 转换为 TIMESTAMP

在 Scala 中将 JSON 转换为 CSV?

在scala中将Spark Dataframe转换为RDD

如何在 Scala 中将 RDD 转换为二维数组?

在Scala中将元组转换为数组