1

例如,我们定义了一个函数,应该将 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 ?

4

5 回答 5

3

当您可以轻松地执行此操作并获得完全相同的结果时,我不确定您为什么要使用选项:

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

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

您甚至可以做得更好,既不使用 a 也不使用PartialFunctiona match,只需这样做:

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

这可以节省您编写一次性用品i

于 2014-09-29T08:00:42.790 回答
3

fScala 的 Map 已经是一个偏函数。因此,您可以使用它而不是定义自己的函数,该函数完全符合 Map 的功能 - “从 A 类型的键映射到 B 类型的值”。
所以你所要做的就是:

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' 来满足其他需求。

于 2014-09-29T12:07:09.970 回答
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.

于 2014-09-29T08:00:24.733 回答
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
于 2014-09-29T10:14:33.653 回答
0

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

由于偏函数是一个函数,所以它可以被链接但选项不能,选项是处理空值的方式。

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

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)
于 2014-09-29T08:06:24.127 回答