使用 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
,_
表示(c, _)
中的c
,而c
是List[Int]
类型,所以在我看来,_:::c
应该是两个List[Int]
的串联。它应该符合预期的类型,对吧?
下划线不是有效的变量名称,它们用于忽略变量。 (c, _)
和_ ::: c
中的两个下划线是不相关的。
-
(c, _) => { ... }
完全忽略第二个参数,它就消失了。 -
_ ::: c
是 lambda 表达式x => x ::: c
的快捷方式,它期望一个x
是某些无法推断的未知类型B_
的List[B_]
,因为它不是预期的,并且在您的代码中找不到它。
如果你想在第一个参数前面加上第二个参数,你必须写一些类似的东西
ls.foldLeft(List.empty[Int])((c, x) => x :: c)
甚至
ls.foldLeft(List.empty[Int])(_.::(_))
看,你可以写List(1,2,3).reduce((x, y) => x + y)
或List(1,2,3).reduce(_ + _)
.在这里,(x, y) => x + y
和_ + _
是函数,第一个更明显,第二个是函数,其中每个下划线都替换为其中一个参数。
你在这里所做的是(c, _) => _:::c
试图将两者结合起来。但是,实际上,你只是告诉scala编译器:
- 我有两个集合函数:
c
和另一个被丢弃。 - 此函数返回不指定类型的函数。(例如:
(Int, Int) => (Int => Int) = (a: Int, _) => _ * 2
)
你可以在这里做的是
仅使用下划线重写:
ls.foldLeft(List.empty[Int])(_.::(_))
或重写而不丢弃:
ls.foldLeft(List.empty[Int])((acc, cur) => cur :: acc)
-
ls
- 类型List[Int]
的列表 -
foldLeft
- 从ls
的Int
元素创建新内容。 -
List[Int]()
- 新的东西将是另一个List[Int]
.从一个空的开始。 -
(c, _)
- 每一步收到正在构建的List
,我们称之为c
,以及来自ls
的Int
,但不要给它一个名字(即扔掉它)。 -
_:::c
- 尝试将 2 个列表连接在一起。一个是我们正在构建的c
列表,另一个是......无。这不是List
或Int
.这是一个未命名的参数,但我们没有这些参数。在收到的 2 个参数中,一个被命名为c
,另一个被丢弃。
这是修复它的一种方法:(c, n) => List(n):::c
(将 2 个列表连接在一起)
这是一个更好的解决方法:(c, n) => n::c
(在此列表的头部前面添加一个新元素)
使用未命名参数:ls.foldLeft(List[Int]())(_.::(_))