完成Scala的初学者,并试着立即找出基础知识。
作为教程的一部分,我试图创建一个返回整数列表中最大元素的函数。为了做到这一点,我(暂时)将以下代码放在一起:
def max(xs: List[Int]): Int =
if (xs.isEmpty)
throw new java.util.NoSuchElementException
else
findMax(xs.head, xs.tail)
def findMax(a: Int, b: List[Int]) {
if (b.isEmpty) return a
if (a > b.head)
findMax(a, b.tail)
else
findMax(b.head, b.tail)
}
但是,当我尝试编译它时,第5行会出现类型错误。
[error] /scala/example/src/main/scala/example/Lists.scala:5: type mismatch;
[error] found : Unit
[error] required: Int
[error] findMax(xs.head, xs.tail)
我不得不承认我对这个错误信息感到困惑,因为我不明白编译器如何认为我试图传入一个Unit类型给定逻辑以确保List是在这一行之前不是空的。
有人可以帮忙澄清这个问题吗?
答案 0 :(得分:6)
Scala有两个用于定义函数的结构:
def doSomething(a: Int) { a + 3 }
和
def doSomethingElse(b: Int) = { b + 3 }
第一个被称为过程语法,并且不鼓励它,因为它导致糟糕的假设和令人困惑的代码。这两个函数之间的区别在于doSomething
返回Unit
,而doSomethingElse
返回Int
。如果您不包含=
,则您的函数将不会返回任何内容(换句话说,它会返回Unit
)。
此
def doSomething(a: Int) { a + 3 }
相当于
def doSomething(a: Int): Unit = { a + 3 }
您希望函数findMax
返回一个Int,但由于您不在=
,Scala表示它返回Unit
。这是编译错误的原因。您可以通过编写
def findMax(a: Int, b: List[Int]) = {
或
def findMax(a: Int, b: List[Int]): Int = {
通常,您不应该使用过程语法。始终使用=
,即使您最终将最终返回类型保留为类型推断。
应该注意的是,第一种方法实际上可能会导致编译器错误,因为您在函数中使用了return
。需要显式调用return
的函数来指定它们在函数头中返回的类型。因为Scala是一种基于表达式的语言,所以每个语句都是一个表达式,因此返回一个值。您可以将findMax
函数重写为不需要return
,如下所示:
def findMax(a: Int, b: List[Int]): Int = {
if (b.isEmpty)
a
else if (a > b.head)
findMax(a, b.tail)
else
findMax(b.head, b.tail)
}