13

在 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
4

5 回答 5

17

我会None尽可能坚持,这几乎总是如此。它更短且被广泛使用。Option.empty允许你指定底层值的类型,所以当你需要帮助类型推断时使用它。如果编译器已经知道该类型None将按预期工作,但是在定义新变量时

var a = None

会导致推断aNone.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

于 2016-03-28T09:10:27.273 回答
5

None如果谈论一个值,例如在将参数传递给任何函数时,使用简短的答案,Option.empty[T]在定义某些东西时使用。

var something = Option.empty[String]手段somethingNone现在,但可以成为Some("hede")未来。另一方面var something = None没有任何意义。你不能用Some("hede")编译器重新分配它会生气: found : Some[String] required: None.type 所以,这意味着None并且Option.empty[T]不是替代品。你可以传递None给任何 Option[T] 但你不能传递 Some[T] 给 None.type

于 2016-03-28T07:54:14.337 回答
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。如何 ?

如您所见,通过var x:Option[String]=None语句中的返回类型让 Scala 知道您的意图很重要。这允许稍后分配Some. 然而,一个简单的var x=None将在后面的行中失败,因为这将使变量 x 解析为None.type而不是Option[T]

我认为应该遵循惯例。对于作业,我会var x:Option[String]=None选择。同样,每当使用 None 时,最好使用返回类型(在本例中为 Option[String]),这样分配就不会解析为None.type.
只有在我无法提供类型并且我需要完成一些任务的情况下,我才会去Option.empty

于 2016-03-28T06:33:33.167 回答
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吗?国际海事组织,我认为 None这是一个不存在的价值,因为文档指定:

    /** This case object represents non-existent values.
     *
     *  @author  Martin Odersky
     *  @version 1.0, 16/07/2003
     */
    
于 2016-03-28T06:51:16.017 回答
0

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

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

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

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

  • 第一个 ( Seq()) 容易出错。看起来如果有人想创建一个序列并忘记添加元素
  • 第二个 ( Seq.empty) 明确表示希望拥有一个空序列
  • 虽然第三个 ( Seq.empty[Type]) 与第二个一样明确,但它更冗长,所以我通常不使用
于 2016-03-28T19:13:55.093 回答