将“Convert”选项[x]转换为x。

38

我正在使用Scala(2.1)进行编程,需要将一个Option[Long]类型的值转换成Long类型。

我知道如何实现相反的操作,也就是说:

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

但是在我的情况下,我必须将一个Option[Long]类型的值传递给一个接受Long类型的方法。

6个回答

66
如果你有一个类型为 Option[Long] 的 x,x.get 将会给你一个 Long 类型的结果。

7
这个答案是错误的。如果 x 是 None (这是 Option[Long] 的一个可能值),调用 get 会抛出错误。 - Andres F.
18
我们可以使用 x.getOrElse(None)。(说明:x.getOrElse(None) 是一种 Scala 语言中的方法调用,它的作用是获取变量 x 的值,如果 x 为 null,则返回 None。) - user3886907
3
更好的选择是使用 x.getOrElse()。 - Cristian Hoyos
1
这个回答怎么会比被采纳的答案获得更多的赞,这是怎么回事?这个回答非常有害。可以参考https://github.com/alexandru/scala-best-practices/blob/master/sections/2-language-rules.md#210-must-not-use-optionget了解详情。我建议直接删除这个回答。 - Evgeny Veretennikov

33

首先,你的“相反”实现存在一些严重问题。通过在方法上放置名为Long的类型参数,你会遮蔽来自标准库的Long类型。你可能的意思是以下内容:

首先,你的“相反”实现存在一些严重问题。通过在方法上放置名为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为空,则此方法将返回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 问题。使用 Option 上的 map 允许您对可能存在于 Option 中的值执行计算,同时继续模拟它为空的可能性。

正如另一个答案所指出的那样,也可以使用 getOrElse 来“退出” Option,但这通常不是 Scala 中的惯用做法(除非确实存在合理的默认值情况)。


如果我们需要一个长的实现需求,那么getOrElse是唯一的方法吗? - rahul

11

该方法已定义在类型为 Option[A] 的对象上,称为 get

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

scala> x.get
res0: Long = 99

问题在于对None调用get方法会抛出NoSuchElementException异常:

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

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

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

Scala的惯用方式是使用map或for循环。

x map (_ + 1)
res2: Option[Long] = Some(100)
或者
for (i <- x) yield i +1
res3: Option[Long] = Some(100)

4

Option是本地化副作用的方法(您的函数可以返回空值)。将计算提升到Option是一种很好的风格(Option是具有mapflatMap方法的Monad)。

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

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

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

1

当选项为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

如果没有非常好的理由,请不要使用nullopt.orNull除外)。

0

如已经提到的那样,getOrElse 可能是您直接回答问题所寻找的答案。

请注意,要转换为选项,您可以简单地执行以下操作:

val myOption = Option(1)

myOption现在将变为Some(1)

val myOption = Option(null)

现在,myOption将变为None。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接