我遇到了这个 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
}
我遇到了这个 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
}
首先,您定义了一个名为的函数iterate
,并将返回类型指定为Int
. 它有 arity 1,l
类型参数List[Int]
。
该List
类型在整个函数式编程中都很突出,它的主要特征是它具有高效的前置,并且很容易将任何内容分解List
为头部和尾部。头部将是列表的第一个元素(如果非空),尾部将是其余的List
(本身是 a List
) - 这对于在 上运行的递归函数非常有用List
。
这match
被称为模式匹配。它本质上是switch
C 语言中的一个语句,但功能更强大 - 将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 :: oldList
is 语法糖,使其更易于阅读。
我们可以定义oldList
为
val oldList = 1 :: 2 :: 3 :: Nil
whereNil
代表一个空的List
。将其分解为以下步骤:
3 :: Nil
首先求值,创建List(3)
具有头部 3 和空尾部的 a 的等价物。List(3)
。List(2, 3)
。List
的结果List(1, 2, 3)
分配给val oldList
.
现在,当您使用::
模式匹配时,您实际上将 a 分解List
为头部和尾部,就像我们创建List
上面的方式相反。当你这样做时
l match {
case h :: t => ...
}
你是说如果可能的话分解l
成一个头和一个尾巴。如果你成功分解,你可以使用这些h
和t
变量来做任何你想做的事情。通常你会做一些类似h
的事情,然后调用递归函数 on t
。
这里要注意的一件事是你的代码不会编译..你做了一个if (h > n) 0
但没有明确else
的所以发生的事情是你的代码对编译器看起来像这样:
if (h > n) 0
else { }
它有类型AnyVal
(常见的超类型0
和“无”),违反了你的Int
保证 - 你将不得不添加一个else
带有一些失败值或其他东西的分支。
第二个case _ =>
就像default
中的 a ,它捕获第一个中switch
的头/尾分解失败的任何内容case
。
您的代码基本上是这样做的:
l
List
参数,看看能不能分解成头尾。n
. 如果大于n
,则函数返回 0。(如果不大于,则需要添加发生的情况)这称为模式匹配。这就像一个switch
声明,但更强大。
一些有用的资源:
http://www.scala-lang.org/node/120
http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-4