首页 > 解决方案 > Scala 函数返回行为

问题描述

我正在尝试解决这个 epfl scala 课程作业,他们要求我写一个列表的总和。如果我使用 return 语句或 if 使用 match 语句,我可以做到这一点,但我不明白为什么在没有 return 语句的情况下使用 if/else 不起作用。

def sum(xs: List[Int]): Int = xs {
  if (xs.isEmpty) {
    0
  } else {
    xs.head + sum(xs.tail)
  }
}

我运行 sum(List(1,3,2)) 时得到的运行时错误是

java.lang.IndexOutOfBoundsException: 0
  at scala.collection.LinearSeqOptimized.apply(LinearSeqOptimized.scala:67)
  at scala.collection.LinearSeqOptimized.apply$(LinearSeqOptimized.scala:65)
  at scala.collection.immutable.List.apply(List.scala:89)
  at example.Lists$.sum(Lists.scala:39)
  at example.Lists$.sum(Lists.scala:39)
  at example.Lists$.sum(Lists.scala:39)
  at example.Lists$.sum(Lists.scala:39)

如果我将代码中的 0 替换为 100 ,则错误消息将更改为 java.lang.IndexOutOfBoundsException: 100 。就像它正在尝试访问列表的第 N 个元素,而我所需要的只是返回。如果我添加两个返回语句,则所有操作都按预期工作。

你能解释一下吗?

标签: scalarecursion

解决方案


根本原因在函数声明的第一行:

def sum(xs: List[Int]): Int = xs {

这相当于:

def sum(xs: List[Int]): Int = xs.apply(<Some function>) 

例如xs.apply(3)意味着从列表中获取索引为 3 的项目xs

Scala 将评估括号内的代码,并尝试将结果应用到xs. 当它展开递归时,它最终会到达一个空列表,但程序要求它返回xs(0)不存在的列表,因此出现IndexOutOfBoundsException错误。

要让这个程序做你想做的事情,只需xs从你的函数体的开头删除:

def sum(xs: List[Int]): Int = {

现在:

sum(List(1,3,2))
res0: Int = 6

推荐阅读