0

使用 foldLeft 函数在 Scala 中使用函数来反转列表:

def reverseWithFold(ls: List[Int]): List[Int] =
        ls.foldLeft(List[Int]())((c, _) => _:::c)

它出现编译错误:Expression of type List[B_] => List[Int] doesn’t comforrm to expected type List[Int](PS:我知道我的解决方案不正确)

我能知道这是什么意思吗?在_:::c这里, the_代表cin (c, _), andc是一个List[Int]类型,所以在我看来,_:::c应该是两个 的串联List[Int]。它应该符合预期的类型,对吧?

4

3 回答 3

3
  • ls- 类型列表List[Int]
  • foldLeftInt- 从元素中创造新的东西ls
  • List[Int]()- 新的东西将是另一个List[Int]。从一个空的开始。
  • (c, _)- 随着每一步接收List正在构建的,我们将调用它c,和一个Intfrom ls,但不要给它一个名字(即扔掉它)。
  • _:::c- 尝试将 2 个列表连接在一起。一个是c我们正在构建的列表,另一个是……什么都没有。它不是一个List或一个Int。这是一个未命名的参数,但我们没有这些参数。在收到的 2 个参数中,一个被命名c,另一个被丢弃。

这是解决它的一种方法:((c, n) => List(n):::c将 2 个列表连接在一起)

这是修复它的更好方法:((c, n) => n::c在此列表的开头添加一个新元素)

使用未命名参数:ls.foldLeft(List[Int]())(_.::(_))

于 2019-01-16T08:12:24.610 回答
3

你看,你可以同时写List(1,2,3).reduce((x, y) => x + y)List(1,2,3).reduce(_ + _)。在这里,(x, y) => x + y_ + _是函数,第一个更明显,第二个是函数,其中每个下划线都被一个参数替换。

您在这里所做的(c, _) => _:::c是试图将两者结合起来。但是,实际上,您只是告诉 scala 编译器:

  1. 我有两个agruments的功能:c另一个被丢弃。
  2. 此函数返回没有指定类型的函数。(例如(Int, Int) => (Int => Int) = (a: Int, _) => _ * 2:)

你可以在这里做的是

仅使用下划线重写:

ls.foldLeft(List.empty[Int])(_.::(_))

或重写而不丢弃:

ls.foldLeft(List.empty[Int])((acc, cur) => cur :: acc)
于 2019-01-16T08:18:50.697 回答
3

下划线不是有效的变量名,它们用于忽略变量。(c, _)和中的两个下划线_ ::: c无关。

  • (c, _) => { ... }完全忽略第二个参数,它就消失了。
  • _ ::: c是 lambda 表达式 的快捷方式x => x ::: c,它期望xa是某种无法推断的List[B_]未知类型,因为它不是预期的,并且在您的代码中无处可寻。B_

如果您想将第二个参数添加到第一个参数之前,则必须编写类似

ls.foldLeft(List.empty[Int])((c, x) => x :: c)

甚至

ls.foldLeft(List.empty[Int])(_.::(_))
于 2019-01-16T08:21:23.580 回答