用功能代码替换if-else

时间:2013-08-19 10:10:12

标签: scala functional-programming pattern-matching

我知道在功能样式中,所有if-else块都被模式匹配所取代。但是我如何处理Scala中模式匹配的Map?例如,我如何以更多功能样式重写此代码?

  val myMap= getMap()
  if(myMap.contains(x) && myMap.contains(y)) Some(myMap(x) + myMap(y))
    else if(myMap.contains(x + y)){
      val z = myMap(x + y)
      if (z % 2 == 0) Some(z)
      else None
    }
    else None

4 个答案:

答案 0 :(得分:19)

使用if-else对于函数式编程是完全可以接受的,因为Scala中的if-else只是一个表达式。决定if-else和模式匹配的原因应该主要集中在提高可读性上。

这是我尝试重写您的代码。我实际上并没有在这里使用模式匹配,而是使用for - 理解来对值进行求和。

def sumOfValues = for{
  mx <- myMap.get(x)
  my <- myMap.get(y)
} yield mx + my

def valueOfSumIfEven = myMap.get(x+y).filter(_ % 2 == 0) 

sumOfValues orElse valueOfSumIfEven

答案 1 :(得分:3)

要直接回答您的问题 - 您可以使用附加的if:

过滤案例
getMap match {
  case myMap if (myMap.contains(x) && myMap.contains(y)) =>
     Some(myMap(x) + myMap(y))
  case myMap if (myMap.contains(x+y)) =>
    myMap(x+y) match {
      case z if (z % 2 == 0) => Some(z)
      case _                 => None
    }
  case _ => None
}

([编辑:实际上]虽然Scala中有“else-if's”,但这实际上是一种做if-else-if-else的方式(查看生成的类文件这是什么呢)实际上,而if-else等同于三元?:在java中,当最后的else丢失时隐式返回Unit。)

答案 2 :(得分:2)

怎么样:

myMap.get(x)
    .zip(myMap.get(y))
    .headOption.map(x => x._1 + x._2)
    .orElse(myMap.get(x + y)
    .filter(__ % 2 == 0))

答案 3 :(得分:1)

嗯,你可以编写你的测试,如下所示:

myMap.get(x).flatMap(xVal => myMap.get(y).map(_ + xVal))
            .orElse(myMap.get(x+y).filter(_ % 2 == 0))

但是,对于任何想要理解意图的人来说,你已经可以更清楚了。请注意,第一行(从flatMap到结尾)也可以写成for-comprehension,如@ ziggystar的回答所示。

如果感觉更清洁,也许模数测试部分可以重写为匹配:

if(myMap.contains(x) && myMap.contains(y))
    Some(myMap(x) + myMap(y))
else myMap.get(x + y) match {
    case Some(z) if (z % 2 == 0) => Some(z)
    case _ => None
  }