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
  }
}
4

2 に答える 2

19

はい、これはマッチの乱用です。基本的に、大きな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)
  }
}
于 2012-09-23T21:09:57.260 に答える
2

いいえ、なぜ虐待するのですか?それはかなり読みやすいIMOです...

私が見ている問題は、それmoney match ...がかなり恣意的であるということです(最初のケースでは直接パターンのみを使用します)。完全な「虐待」は次のように始まります

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

したがって、おそらくif-elseに固執します。2番目と3番目の条件を組み合わせることができます(if( money < 0 || coins.isEmpty ) ...


また、コインが空ではないことを「知っている」ので、「安全に」呼び出すことができますが、これは予期しないランタイムエラーの典型的な原因であることに注意してheadくださいtail。の利点coins match { case Nil => ...; case head :: tail => ...}は、そのような間違いを犯すことはできないということです。

于 2012-09-23T21:10:29.800 に答える