Scala Match Case 结构和遍历具有奇数项 cs 和 m 的列表?

Scala Match Case structure and traversing a List with odd terms cs and m?

我正在尝试理解这段代码here

  def countChange(money: Int, coins: List[Int]): Int = (money, coins) match {
     case (0, _) => 1
     case (m, _) if m < 0 => 0
     case (_, cs)  if cs.isEmpty => 0
     case (m, cs) => countChange(m - cs.head, cs) + countChange(m, cs.tail) 
  }
}

我无法理解 (0,_)(m,_)(_,cs)(m,cs) 对,因为术语 mcs 未定义在代码正文中。

遍历List的这个构造叫什么?一对匹配的模式?

正在递归遍历列表。此构造称为 pattern matching

你可以这样读:

If the tuple (money, coins) is a tuple whose first value is 0 then return 1 ignore the second value of the tuple

If the tuple (money, coins) is a tuple has a first value below 0 then return 0 ignore the second value of the tuple.

等等...

_在模式匹配中用来简化我们不关心那个参数是什么,它可以是任何东西

Scala 中的模式匹配由对象的 unapply 方法支持,阅读更多内容 about extractors。这意味着对于每个 case 方法 unapply 将以元组 (money, coins) 作为参数调用,如果确定它是匹配项,它将相应的第一个值和第二个值传递给 case 个子句。

示例:

语句case (m, _) => ...将导致调用Tuple2.unapply((money, coins))

备注

案例 class 已经为我们定义了 unapply 方法。这就是为什么你可以在模式匹配中使用它们 'out of the box'。 Tuple2 是个案 class.

这是一个模式匹配的例子,它被用来递归地遍历你的硬币列表。这是用注释重写的相同代码,重要的是要知道每个 case 语句匹配元组的一个可能模式,而 _ 用于忽略元组的片段。

def countChange(money: Int, coins: List[Int]): Int = {

  // Construct a tuple for pattern matching on
  val tuple: (Int, List[Int])  = (money, coins)

  tuple match {

    // Check to see if money == 0
    case (0, _) => 1

    // m represents money, use a guard to check if m is negative 
    case (m, _) if m < 0 => 0

    // cs represents coins, use a guard statement check for empty list
    case (_, cs) if cs.isEmpty => 0

    // Recursive step.  Since the patterns are tried in order, we 
    // now know that if we make it to here m (money) is non-zero 
    // and non-negative, and we know that cs (coins) is a non-empty 
    // list.  Now we can  call the recursive function safely on 
    // the head of the list
    case (m, cs) => countChange(m - cs.head, cs) + countChange(m, cs.tail)
  }

}

这一结构通常用于同时匹配多个变量。在 match 的顶部,您会看到 (money, coins)。这意味着它在 moneycoins 上匹配。它没有名字,因为它是同时对两个值进行完美的普通匹配。

I cannot understand the pairs (0,_), (m,_), (_,cs) and (m,cs) because the terms m and cs are undefined in the body of the code.

这些术语在代码中定义的。 case 定义了它们。这就是匹配和解构的意义所在。

(money, coins) match {
   case (0, _) => 1 // If money == 0, then coins is ignored and we return 1
   case (m, _) if m < 0 => 0 // m = money, coins is ignored. If m < 0, return 0
   case (_, cs)  if cs.isEmpty => 0 // money is ignored, cs = coins.
                                    // If we have no coins, return 0.
   case (m, cs) => countChange(m - cs.head, cs) + countChange(m, cs.tail)
   // Otherwise, m = money, cs = coins. Recurse down the list with
   // countChange(money - coins.head, coins) + countChange(money, coins.tail)
}

元组 (money, coins) 的原因是因为这些模式依赖于 moneycoins。您要么需要嵌套 matchs(丑陋),要么需要执行更丑陋的布尔逻辑才能复制这些语义。