0

我遇到了这个 scala 代码,我试图弄清楚它在做什么,除了它返回一个 int 的事实。我不确定这三行:

  l match {
  case h :: t =>
  case _ => 0

功能 :

def iterate(l: List[Int]): Int = 
  l match {
  case h :: t =>
    if (h > n) 0 
  case _ => 0
} 
4

2 回答 2

16

首先,您定义了一个名为的函数iterate,并将返回类型指定为Int. 它有 arity 1,l类型参数List[Int]

List类型在整个函数式编程中都很突出,它的主要特征是它具有高效的前置,并且很容易将任何内容分解List为头部和尾部。头部将是列表的第一个元素(如果非空),尾部将是其余的List(本身是 a List) - 这对于在 上运行的递归函数非常有用List

match被称为模式匹配。它本质上是switchC 语言中的一个语句,但功能更强大 - 将switch您限制为常量(至少在 C 中是这样),但match.

现在,您case拥有的第一个h :: t-::被称为“缺点”,这是函数式编程的另一个术语。List当您通过前置从另一个创建新的时List,您可以使用::运算符来执行此操作。

例子:

val oldList = List(1, 2, 3)
val newList = 0 :: oldList // newList == List(0, 1, 2, 3)

在 Scala 中,以 a 结尾的运算符:实际上是右手边的方法,因此0 :: oldList相当于oldList.::(0)- 0 :: oldListis 语法糖,使其更易于阅读。

我们可以定义oldList

val oldList = 1 :: 2 :: 3 :: Nil

whereNil代表一个空的List。将其分解为以下步骤:

  1. 3 :: Nil首先求值,创建List(3)具有头部 3 和空尾部的 a 的等价物。
  2. 2 附加到上面的列表中,创建一个带有 head 2 和 tail 的新列表List(3)
  3. 1 是前置的,创建一个带有 head 1 和 tail 的新列表List(2, 3)

List的结果List(1, 2, 3)分配给val oldList.

现在,当您使用::模式匹配时,您实际上将 a 分解List为头部和尾部,就像我们创建List上面的方式相反。当你这样做时

l match {
  case h :: t => ...
}

你是说如果可能的话分解l成一个头和一个尾巴。如果你成功分解,你可以使用这些ht变量来做任何你想做的事情。通常你会做一些类似h的事情,然后调用递归函数 on t

这里要注意的一件事是你的代码不会编译..你做了一个if (h > n) 0但没有明确else的所以发生的事情是你的代码对编译器看起来像这样:

if (h > n) 0
else { }

它有类型AnyVal(常见的超类型0和“无”),违反了你的Int保证 - 你将不得不添加一个else带有一些失败值或其他东西的分支。

第二个case _ =>就像default中的 a ,它捕获第一个中switch的头/尾分解失败的任何内容case

您的代码基本上是这样做的:

  1. l List参数,看看能不能分解成头尾。
  2. 如果可以的话,将头部与(我假设的)外部范围中名为n. 如果大于n,则函数返回 0。(如果不大于,则需要添加发生的情况)
  3. 如果无法分解,则函数返回 0。
于 2012-09-20T21:31:36.623 回答
1

这称为模式匹配。这就像一个switch声明,但更强大。

一些有用的资源:

http://www.scala-lang.org/node/120

http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4

于 2012-09-20T20:00:37.870 回答