Scala类型不匹配单元而不是Int

时间:2016-12-10 04:18:07

标签: scala types

完成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是在这一行之前不是空的。

有人可以帮忙澄清这个问题吗?

1 个答案:

答案 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)
}