什么时候应该使用Option.empty [A]什么时候我应该在Scala中使用None?

时间:2016-03-28 06:28:30

标签: scala scala-option

在Scala中,当我想将某些内容设置为None时,我有几个选择:使用NoneOption.empty[A]

我应该选择一个并一直使用它,还是有时我应该使用一个而不是另一个?

示例:

scala> def f(str: Option[String]) = str
f: (str: Option[String])Option[String]

scala> f(None)
res0: Option[String] = None

scala> f(Option.empty)
res1: Option[String] = None

5 个答案:

答案 0 :(得分:10)

我会尽可能坚持None,这几乎总是如此。它更短,使用更广泛。 Option.empty允许您指定基础值的类型,因此在需要帮助键入推断时使用它。如果编译器已知类型None将按预期工作,但是在定义新变量时

var a = None

会导致将a推断为None.type,这不太可能是你想要的。

然后,您可以使用其中一种方式来帮助推断您的需求

@ var a = Option.empty[String]
a: Option[String] = None
@ var a: Option[String] = None
a: Option[String] = None
@ var a = None: Option[String] // this one is rather uncommon
a: Option[String] = None

编译器需要帮助的另一个地方:

List(1, 2, 3).foldLeft(Option.empty[String])((a, e) => a.map(s => s + e.toString))

(代码没有意义,只是作为示例)如果您要省略类型,或将其替换为None,则累加器的类型将被Option[Nothing]None.type所感染分别

对我个人而言,这是我将Option.empty使用的地方,对于其他情况,我会尽可能坚持使用None

答案 1 :(得分:4)

简短回答使用None如果在将参数传递给任何函数时谈论一个值,则在定义某些内容时使用Option.empty[T]

var something = Option.empty[String]表示something目前为None,但将来可能会成为Some("hede")。另一方面,var something = None没有任何意义。你无法用Some("hede")编译器重新分配它会生气: found : Some[String] required: None.type 因此,这意味着NoneOption.empty[T]不是替代品。您可以将None传递给任何选项[T],但不能将某些[T]传递给None.type

答案 2 :(得分:1)

以下是使用Scala和Scalaz的工作表导出。

def f(str: Option[String]) = str              //> f: (str: Option[String])Option[String]
f(None)                                       //> res1: Option[String] = None
var x:Option[String]=None                     //> x  : Option[String] = None
x=Some("test")
x                                             //> res2: Option[String] = Some(test)
x=None
x      

现在使用Scalaz,

def fz(str: Option[String]) = str             //> fz: (str: Option[String])Option[String]
fz(none)                                      //> res4: Option[String] = None
var xz:Option[String]=none                    //> xz  : Option[String] = None
xz=some("test")
xz                                            //> res5: Option[String] = Some(test)
xz=none
xz         

请注意,无论您使用None还是Option.Empty,所有语句都会以相同的方式进行评估。怎么样 ?

正如您所看到的,让Scala通过var x:Option[String]=None语句中的返回类型了解您的意图非常重要。这允许稍后分配Some。但是,简单的var x=None会在以后的行中失败,因为这会使变量x解析为None.type而不是Option[T]

我认为应该遵循惯例。对于作业,我会选择var x:Option[String]=None选项。此外,每当使用None时,最好使用返回类型(在本例中为Option [String]),以便赋值不会解析为None.type
只有在我无法提供类型并且我需要完成某项任务的情况下,我才能进入Option.empty

答案 3 :(得分:1)

鉴于Option[A].empty只返回None

/** An Option factory which returns `None` in a manner consistent with
 *  the collections hierarchy.
 */
def empty[A] : Option[A] = None

我会说:

  1. 正如您所说,在整个代码库中保持一致。使其保持一致意味着进入代码库的程序员可以更少地担心。 “我应该使用None还是Option.empty?嗯,我看到@cdmckay在整个呼叫基础上使用X,我也会使用它”
  2. 可读性 - 想想什么能传达出你最想要的点。如果你要阅读一个特定的方法,如果它返回一个空的Option(让我们忽略了底层实现只是返回None的事实)或一个显式的,那么它会更有意义吗? None? IMO,我认为None是一个不存在的值,正如文档所指定的那样:

    /** This case object represents non-existent values.
     *
     *  @author  Martin Odersky
     *  @version 1.0, 16/07/2003
     */
    

答案 4 :(得分:0)

正如其他人所指出的那样,这更多的是个人品味,大多数人都喜欢None,或者在某些情况下,你明确需要放置类型,因为编译器无法推断

此问题可以外推到其他Scala类,例如SequencesMapSetList等。在所有这些中,您有几种方法可以定义空状态。使用序列:

  • Seq()
  • Seq.empty
  • Seq.empty[Type]

从3开始,我更喜欢第二个,因为:

  • 第一个(Seq())容易出错。看起来好像有人想要创建一个序列而忘记添加元素
  • 第二个(Seq.empty)明确表示有一个空序列的愿望
  • 虽然第三个(Seq.empty[Type])与第二个一样明确,但它更详细,所以我通常不使用