在 Scala 中什么时候应该使用 Option.empty[A] 什么时候应该使用 None?
When should I use Option.empty[A] and when should I use None in Scala?
在 Scala 中,当我想将某些内容设置为 None
时,我有几个选择:使用 None
或 Option.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
以下是使用 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
语句中的 return 类型让 Scala 知道您的意图很重要。这允许稍后分配 Some
。然而,一个简单的 var x=None
将在后面的行中失败,因为这将使变量 x 解析为 None.type
而不是 Option[T]
.
我认为应该遵循惯例。对于作业,我会选择 var x:Option[String]=None
选项。此外,每当使用 None 时,最好使用 return 类型(在本例中为 Option[String]),这样赋值就不会解析为 None.type
.
只有在我无法提供类型并且我需要完成一些任务的情况下,我才会去 Option.empty
鉴于 Option[A].empty
只需 returns None
:
/** An Option factory which returns `None` in a manner consistent with
* the collections hierarchy.
*/
def empty[A] : Option[A] = None
我会说:
- 如您所说,在整个代码库中保持一致。使其保持一致意味着进入您的代码库的程序员可以少担心一件事。 "Should I use
None
or Option.empty
? Well, I see @cdmckay is using X throughout the call base, I'll use that as well"
可读性 - 想一想什么传达了您最想要的观点。如果你要阅读一个特定的方法,如果它返回一个空的 Option
(让我们暂时忽略底层实现只是返回 None
的事实)或一个显式的对你来说更有意义None
? IMO,我认为 None
是一个不存在的值,正如文档所指定的那样:
/** This case object represents non-existent values.
*
* @author Martin Odersky
* @version 1.0, 16/07/2003
*/
简答使用 None
如果在将参数传递给任何函数时谈论一个值,则在定义某些内容时使用 Option.empty[T]
。
var something = Option.empty[String]
表示 something
目前是 None
,但将来可以变成 Some("hede")
。另一方面 var something = None
没有任何意义。你不能用 Some("hede")
重新分配它,编译器会生气:
found : Some[String]
required: None.type
所以,这意味着 None
和 Option.empty[T]
不是替代品。您可以将 None
传递给任何 Option[T] 但不能将 Some[T] 传递给 None.type
只要有可能,我都会坚持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
。
正如其他人指出的那样,这更多是个人品味问题,大多数人更喜欢 None
,或者在某些情况下,您明确需要输入类型,因为编译器不能' t推断。
这个问题可以外推到其他Scala 类,比如Sequences
、Map
、Set
、List
等。在所有这些中,您有几种方法来定义空状态。使用顺序:
Seq()
Seq.empty
Seq.empty[Type]
在第3个中,我更喜欢第2个,因为:
- 第一个 (
Seq()
) 容易出错。看起来如果有人想创建一个序列而忘记添加元素
- 第二个 (
Seq.empty
) 明确表示希望有一个空序列
- 虽然第三个 (
Seq.empty[Type]
) 和第二个一样明确,但更冗长,所以我通常不使用
在 Scala 中,当我想将某些内容设置为 None
时,我有几个选择:使用 None
或 Option.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
以下是使用 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
语句中的 return 类型让 Scala 知道您的意图很重要。这允许稍后分配 Some
。然而,一个简单的 var x=None
将在后面的行中失败,因为这将使变量 x 解析为 None.type
而不是 Option[T]
.
我认为应该遵循惯例。对于作业,我会选择 var x:Option[String]=None
选项。此外,每当使用 None 时,最好使用 return 类型(在本例中为 Option[String]),这样赋值就不会解析为 None.type
.
只有在我无法提供类型并且我需要完成一些任务的情况下,我才会去 Option.empty
鉴于 Option[A].empty
只需 returns None
:
/** An Option factory which returns `None` in a manner consistent with
* the collections hierarchy.
*/
def empty[A] : Option[A] = None
我会说:
- 如您所说,在整个代码库中保持一致。使其保持一致意味着进入您的代码库的程序员可以少担心一件事。 "Should I use
None
orOption.empty
? Well, I see @cdmckay is using X throughout the call base, I'll use that as well" 可读性 - 想一想什么传达了您最想要的观点。如果你要阅读一个特定的方法,如果它返回一个空的
Option
(让我们暂时忽略底层实现只是返回None
的事实)或一个显式的对你来说更有意义None
? IMO,我认为None
是一个不存在的值,正如文档所指定的那样:/** This case object represents non-existent values. * * @author Martin Odersky * @version 1.0, 16/07/2003 */
简答使用 None
如果在将参数传递给任何函数时谈论一个值,则在定义某些内容时使用 Option.empty[T]
。
var something = Option.empty[String]
表示 something
目前是 None
,但将来可以变成 Some("hede")
。另一方面 var something = None
没有任何意义。你不能用 Some("hede")
重新分配它,编译器会生气:
found : Some[String]
required: None.type
所以,这意味着 None
和 Option.empty[T]
不是替代品。您可以将 None
传递给任何 Option[T] 但不能将 Some[T] 传递给 None.type
只要有可能,我都会坚持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
。
正如其他人指出的那样,这更多是个人品味问题,大多数人更喜欢 None
,或者在某些情况下,您明确需要输入类型,因为编译器不能' t推断。
这个问题可以外推到其他Scala 类,比如Sequences
、Map
、Set
、List
等。在所有这些中,您有几种方法来定义空状态。使用顺序:
Seq()
Seq.empty
Seq.empty[Type]
在第3个中,我更喜欢第2个,因为:
- 第一个 (
Seq()
) 容易出错。看起来如果有人想创建一个序列而忘记添加元素 - 第二个 (
Seq.empty
) 明确表示希望有一个空序列 - 虽然第三个 (
Seq.empty[Type]
) 和第二个一样明确,但更冗长,所以我通常不使用