【问题标题】:Handle Scala Option idiomatically惯用地处理 Scala 选项
【发布时间】:2014-01-30 21:11:57
【问题描述】:

处理Optionmap / getOrElsematch 的更惯用的方法是什么?

val x = option map {
  value => Math.cos(value) + Math.sin(value)
} getOrElse {
  .5
}

val x = option match {
    case Some(value) => Math.cos(value) + Math.sin(value)
    case None => .5
}

【问题讨论】:

  • 这个问题不应该因为主要基于意见而关闭。来自 Python,我知道在 SO 上有数百个关于最“Pythonic”(惯用)方法的问题。

标签: scala scala-option


【解决方案1】:

你总是可以只看Scaladoc for Option

使用 scala.Option 实例最惯用的方式是将其视为集合或 monad,并使用 map、flatMap、filter 或 foreach:

val name: Option[String] = request getParameter "name"
val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
println(upper getOrElse "")

稍后:

使用 scala.Option 值的一种不太惯用的方法是通过模式匹配:

val nameMaybe = request getParameter "name"
nameMaybe match {
  case Some(name) =>
    println(name.trim.toUppercase)
  case None =>
    println("No name value")
}

【讨论】:

  • 我不会也不会反对,但请注意match 构造编译为内联代码。 HOF 需要一流的函数,这些函数每个都生成一个类来捕获它们的主体,并且每次使用它们时都必须实例化。因此,在开销很重要的情况下(众所周知的内部循环),可能需要匹配。此外,我认为大多数人发现它们比 HOF 在适用时更容易掌握,这或多或少意味着当它们单独使用时。在用于理解的一元链中,这只是唯一的方法。
  • 有趣...他们没有提到折叠
  • Scala 2.10 没有使用fold 的机会。此外,人们通常会在 foldmap().getOrElse() 的可读性上有所不同。但我想说两者都是惯用的,而且都比 match 更惯用。
【解决方案2】:

使用 fold 来处理这种默认的 map-or-else-default 事情:

val x = option.fold(0.5){ value => Math.cos(value) + Math.sin(value) }

【讨论】:

  • 虽然它确实从“惯用”的角度回答了这个问题,但 Option 的变态很难理解。来自代码可维护性 POV 的 -1。请参阅有关该主题的讨论和结论:apache-spark-developers-list.1001551.n3.nabble.com/…
  • fold 的参数顺序似乎是该讨论的一个症结所在;值得注意的是,Scalaz 证明了具有预期参数顺序的.cata 扩展方法:option.cata(value => cos(value) + sin(value), 0.5)。通过拥有一个单一的参数列表,它还避免了由于过于具体的推断类型破坏东西而导致的常见问题。
【解决方案3】:

显然两者都是有效的,我认为没有一个比另一个更惯用。话虽如此,使用 map 使用 Option 是 Monad 的事实。这在组合两个选项时特别有利。假设您有两个 Option[Int] 要添加。在这种情况下,与其进行多次匹配,不如使用 map/flatMap 更简洁,它相当于“用于理解”。因此,对于您的示例,两者都是有效的......但对于使用 map/flatMap 的其他示例,通常要简洁得多。

Some(6).flatMap(intValue => Some(5).map(intValue + _))

for {
   i <- Some(6)
   j <- Some(5)
} yield i + j

【讨论】:

    【解决方案4】:

    它们都有不同的语义,所以在你的情况下它们都没有。

    map 将一些函数应用于Option 中的值,如果它存在的话(Some,而不是None)。基本上这就是你如何安全地使用Options,在某些null 值上应用函数是危险的,因为它可能会抛出 NPE,但如果使用 Option,它只会返回 None。

    getOrElse 只返回它的值或默认值(您将其作为参数提供)。它不会对Option 中的值做任何事情,如果你有Some,你可以直接提取它,或者返回一个默认值,如果是None。

    我认为match 方法是两者的结合,因为您可以对这些值应用一些计算并从Option 中提取它

    【讨论】:

      猜你喜欢
      • 2014-04-25
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 2021-07-01
      • 1970-01-01
      • 2014-12-21
      • 1970-01-01
      相关资源
      最近更新 更多