我是来自Java背景的Scala新手,目前对考虑的最佳实践感到困惑Option[T].
我觉得使用Option.map它更实用,更美观,但这并不是说服其他人的好理由.有时,isEmpty检查感觉更直接,因此更具可读性.有客观上的优势,还是个人偏好?
例:
变化1:
someOption.map{ value =>
{
//some lines of code
}
} orElse(foo)
Run Code Online (Sandbox Code Playgroud)
变化2:
if(someOption.isEmpty){
foo
} else{
val value = someOption.get
//some lines of code
}
Run Code Online (Sandbox Code Playgroud)
我故意排除使用fold或模式匹配的选项.我现在对Option作为一个集合处理的想法感到高兴,并且使用模式匹配进行简单的isEmpty检查是滥用模式匹配恕我直言.但无论我为什么不喜欢这些选项,我都希望将这个问题的范围保持为标题中指定的上述两种变体.
有客观上的优势,还是个人偏好?
我认为客观优势与个人偏好之间存在细微差别.你不能让人相信任何一个人都有绝对的真理.
使用Scala构造的一元性质所获得的最大优势是组合.的能力,以连锁经营在一起,而不必"担心"关于内在价值是强大,不仅有Option[T],而且还与工作Future[T],Try[T],Either[A, B]和来回它们之间(见单子变形金刚).
让我们试着看看如何使用预定义方法Option[T]来帮助控制流程.例如,考虑这样一种情况,Option[Int]即只有当它大于某个值时才有多个,否则返回-1.在命令式方法中,我们得到:
val option: Option[Int] = generateOptionValue
var res: Int = if (option.isDefined) {
val value = option.get
if (value > 40) value * 2 else -1
} else -1
Run Code Online (Sandbox Code Playgroud)
使用集合样式方法Option,等效看起来像:
val result: Int = option
.filter(_ > 40)
.map(_ * 2)
.getOrElse(-1)
Run Code Online (Sandbox Code Playgroud)
我们现在考虑一个组合案例.假设我们有一个可能抛出异常的操作.此外,此操作可能会或可能不会产生价值.如果它返回一个值,我们想要用该值查询数据库,否则返回一个空字符串.
看一下try-catch块的命令式方法:
var result: String = _
try {
val maybeResult = dangerousMethod()
if (maybeResult.isDefined) {
result = queryDatabase(maybeResult.get)
} else result = ""
}
catch {
case NonFatal(e) => result = ""
}
Run Code Online (Sandbox Code Playgroud)
现在让我们考虑scala.util.Try一起使用Option[String]和组合两者:
val result: String = Try(dangerousMethod())
.toOption
.flatten
.map(queryDatabase)
.getOrElse("")
Run Code Online (Sandbox Code Playgroud)
我认为这最终归结为哪一个可以帮助您创建清晰的操作控制流程.习惯使用Option[T].map而不是Option[T].get使代码更安全.
总结一下,我不相信有一个单一的事实.我相信组合可以导致美观,可读,副作用延迟安全代码,我全力以赴.我认为向他人展示你的感受的最佳方式是给我们看到的例子,并让他们感受到他们可以利用这些工具集的力量.
使用模式匹配进行简单的 isEmpty 检查是对模式匹配恕我直言的滥用
如果您只是想要一张isEmpty支票,isEmpty/isDefined就完全没问题。但就你而言,你也想获得价值。为此使用模式匹配并不是滥用;而是使用模式匹配。这正是基本用例。使用get允许很容易犯错误,例如忘记检查isDefined或进行错误检查:
if(someOption.isEmpty){
val value = someOption.get
//some lines of code
} else{
//some other lines
}
Run Code Online (Sandbox Code Playgroud)
希望测试能够发现它,但没有理由满足于“希望”。
组合器(map和朋友)比模式匹配更好,get原因相同:它们不允许您犯这种错误。在模式匹配和组合器之间进行选择是一个不同的问题。一般来说,组合器是首选,因为它们更具可组合性(正如尤瓦尔的回答所解释的那样)。如果你想做一些由单个组合器涵盖的事情,我通常会选择它们;map ... getOrElse如果您需要像, 或具有多行分支的组合fold,则取决于具体情况。