滥用match功能?

6
你会考虑以下代码块是否属于滥用,如果是的话,有没有更优雅的方法可以避免使用大量的if-else-if语句?
def sum(base: Int, xs: List[Int]): Int = {
  base match {
    case 0 => 1
    case _ if (base < 0) => 0
    case _ if (xs.isEmpty) => 0
    case _ => xs.sum
  }
}

与我的countChange实现非常相似,但我使用了一个内部函数 :) - sbenitezb
1
你知道Martin Odersky的《Scala函数式编程原理》课程的荣誉守则吗?“我不会将作业、测验或考试的解答提供给任何其他人。” - user425367
2
@som-snytt 我不确定我是否理解你的意思(我的目标是Chris)。 Chris提供的代码是课程评分人员将授予您完整分数的答案。 不是答案,而是问题代码。 荣誉准则非常明确,如果您已经注册了该课程,那么您不会错过它。“我不会向任何其他人提供作业,测验或考试的解决方案。这包括我写的解决方案以及课程工作人员提供的任何官方解决方案。” - user425367
抱歉,我没有意识到在未提及课程的情况下发布我的解决方案会成为一个问题。找零问题很常见,实现也可以在许多语言中轻松地在线获取,包括Scala。我很乐意重新制作一个更通用的示例,但这可能会让查看dhg答案的任何人感到困惑。 - Chris
2
我能否向大家解释一下,Stack Overflow的版主并不负责监管非Stack Exchange社区的条款、条件、"荣誉准则"、版权侵犯等问题。这是Coursera需要直接与Stack Exchange沟通的事情。 - Kev
示例已被编辑为通用(从而变得毫无意义)。 - Chris
2个回答

19

是的,这是对match方法的滥用。实际上你只是用一种更加笨拙的形式写了一个大的if-else-if块。使用if语句有什么问题吗?

我认为这样更加清晰简洁:

def countChange(money: Int, coins: List[Int]): Int = {
  if(money == 0) 1
  else if (money < 0) 0
  else if (coins.isEmpty) 0
  else countChange(money, coins.tail) + countChange(money - coins.head, coins)
}

如果您想坚持使用match,可以将更多的检查移入匹配本身,以便它真正做一些事情:

def countChange(money: Int, coins: List[Int]): Int = {
  (money, coins) match {
    case (0, _) => 1
    case _ if (money < 0) => 0
    case (_, Nil) => 0
    case (_, coinsHead :: coinsTail) => countChange(money, coinsTail) + countChange(money - coinsHead, coins)
  }
}

个人认为,问题中的match/case版本比一系列的if/else if更清晰、视觉上更舒适。由于=>,它在条件和结果表达式之间有更多的分离。此外,我可以立即知道money match { ... }将是一个表达式,而很难说if表达式何时结束。 - huynhjl
在我看来,使用 if/else 更易读,但如果我要使用 match,我会尝试缩写。我会将第二个 case 写成 case (m, _) if (m < 0) => 0,将最后一个 case 写成 case (m, h :: t) => countChange(m, t) + countChange(m - h, coins) - Aaron Novstrup
7
请注意,您在 Martin Odersky 的 Scala 函数式编程原理课程的评分作业中发布了一个解决方案。我明白您可能不需要在意,因为您并没有注册这门课程,但最好删除您的答案,因为它会被搜索引擎索引,从而暗示鼓励作弊行为。 - user425367

2

不需要滥用吧?我认为这段代码很易读...

我看到的问题是,money match ... 相对随意(你只在第一个情况下使用了直接模式);完全的“滥用”会像这样开始:

() match {
  case _ if (money == 0) => 1
  ...

所以也许最好使用if-else; 你可以将第二和第三个条件结合起来 (if( money < 0 || coins.isEmpty ) ...)


还要注意,尽管你“知道”coins不为空,因此可以“安全地”在其上调用headtail,但这是意外运行时错误的典型来源。 coins match { case Nil => ...; case head :: tail => ...} 的优点是您不会犯这样的错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接