【问题标题】:Scala Type Mismatch Unit Instead of IntScala 类型不匹配单元而不是 Int
【发布时间】:2016-12-10 14:42:08
【问题描述】:

完全是 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 不为空行。

谁能帮助澄清这里的问题?

【问题讨论】:

    标签: scala types


    【解决方案1】:

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

    【讨论】:

    • 过程语法在 -Xfuture 下已弃用。我想这就是原因。
    • 谢谢你,你澄清的事情比我意识到的更多让我困惑!如果我可以问一个后续问题,你能解释一下抛出异常时返回的内容吗?具体来说,我最初想将第 2 行和第 3 行放在一起作为保护子句而不是 if-else 条件的一部分,但这会导致另一个类型不匹配的实例(Unit 而不是 Int),然后编译器继续说“xs”有在调用 findMax 函数时没有值。
    • throws 是一个非常特殊的情况。它不返回。 trys 也不会捕获抛出的异常类型。在这种情况下,throwstry 的返回类型是一种特殊的底部类型,称为Nothing。没有Nothing 的实例——甚至null 也不是NothingNothing 是所有事物的子类型,因此 if 在一个分支中返回 Nothing 而在另一个分支中返回 Int 最终返回 Int,因为这是两个分支中最低的常见类型。
    • 如果我理解正确,你有一个if 没有else?这并没有错。您的类型错误可能是因为 findMax 正在返回 Unitmax 应该返回 Int
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    • 2012-08-27
    • 2017-10-31
    • 2023-03-06
    • 2018-08-02
    • 1970-01-01
    相关资源
    最近更新 更多