如何知道何时使用PartialFunction vs return Option

时间:2014-09-29 07:47:43

标签: scala partial-functions

作为一个例子,我们定义了一个函数,它应该分别将1,3,42转换为" foo"," bar"," qix"和所有其他整数到" X"。

我提出了2个实现: 方法f需要分开,因为它可以在其他上下文中重用。

def f(i: Int): Option[String] = i match {
  case 1 => Some("foo")
  case 3 => Some("bar")
  case 42 => Some("qix")
  case _ => None
}

def g(i: Int) : String = f(i).getOrElse("X")

并且:

def f_ : PartialFunction[Int, String] = {
  case 1 => "foo"
  case 3 => "bar"
  case 42 => "qix"
}

def g_(i: Int) : String = f_.orElse { case _ => "X" }(i)

我倾向于选择第二种,因为它避免了许多重复的Some(...)

WDYT?

5 个答案:

答案 0 :(得分:3)

我不确定你为什么要使用选项,只要你可以轻松地做到这一点并获得完全相同的结果:

def f(i: Int): String = i match {
  case 1  => "foo"
  case 3  => "bar"
  case 42 => "qix"
  case _  => "X"
}

它甚至可以为您节省一个讨厌的getOrElse

你甚至可以更好地使用PartialFunctionmatch而只是这样做:

def f: Int => String = {
  case 1  => "foo"
  case 3  => "bar"
  case 42 => "qix"
  case _  => "X"
}

这可以节省您写一次性i

的费用

答案 1 :(得分:3)

fScala的地图已经是部分功能。所以你可以使用它而不是定义你自己的函数,它完全符合Map的作用 - "从A类型的键到B型和#34的值的映射;。
所以你要做的就是:

val f = Map(1 -> "foo", 3 -> "bar", 42 -> "qix")
def g(i: Int) = f.getOrElse(i, "X")

f(1)  //foo
f(4)  // throw NoSuchElementException: Key not found: 4
f.get(1) // Some(foo)
f.get(4) // None
g(1)  //foo
g(4)  //X

现在您可以使用' g'或重复使用' f'满足其他需求。

答案 2 :(得分:1)

根据你的评论编辑我的例子:

def f(i: Int): Option[String] = {
  val map = Map(1 -> "foo", 3 -> "bar", 42 -> "qix")
  i match {
    case x if (map.contains(x)) => Some(map(x))
    case _ => None
  }
}

def g(i: Int) : String = f(i).getOrElse("X")

我认为函数应该以某种有意义的方式对给定范围之外的整数作出反应。这就是为什么我更喜欢Option

答案 3 :(得分:0)

选项是处理空值的好方法。 部分功能只是部分匹配,它们不相同,即使Option和PartialFunction都有类似的 orElse 方法

由于部分功能是功能,所以它可以链接但选项不能,Option是处理空值的方法。

对于你可以这样做的部分功能,它更像是责任链

def f_1 : PartialFunction[Int, String] = {
  case 1 => "1"
}

def f_2 : PartialFunction[Int, String] = {
  case 2 => "2"
}

def f_3 : PartialFunction[Int, String] = {
  case 3 => "3"
}

f_1.orElse(f_2).orElse(f_3)(3)

答案 4 :(得分:0)

您可能想尝试一下。这里HashMap为您提供快速查找:

object SomeMain {
  import scala.collection.immutable.HashMap
  def f(i: Int): Option[String] = {
    HashMap(1 -> "foo", 3 -> "bar", 42 -> "qix").get(i).orElse(None)
  }

  def g(i: Int): String = f(i).getOrElse("X")

  def main(args: Array[String]) {
    List(1, 3, 42, 10) foreach { x => println(x + ": " + g(x)) }
  }
}

输出:

1: foo
3: bar
42: qix
10: X