在 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)
当且仅当value
为null
时,此方法才会返回None
。
为了解决您的问题,假设我们有以下方法:
def foo(x: Long) = x * 2
您通常不应该考虑将Option[Long]
传递给foo
,而是通过map
将foo
“提升”到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,带有 map 和 flatMap 方法)。 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的主要内容,如果未能解决你的问题,请参考以下文章