我正在阅读有关Scala currying here的一些内容,我不太了解这个例子:
def foldLeft[B](z: B)(op: (B, A) => B): B
[B]
是多少?为什么它在括号中?冒号后的B
是返回类型吗?什么类型?看起来这个方法有2个参数列表:一个参数名为z
,另一个参数名为op
,是一个函数。
op
看起来需要一个函数(B, A) => B)
。右边是什么意思?它返回B
?这显然是如何使用的:
val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val res = numbers.foldLeft(0)((m, n) => m + n)
print(res) // 55
发生了什么事?调用时为什么不需要[B
]?
答案 0 :(得分:3)
在Scala文档中,A
类型(有时是A1
)通常是集合元素类型的占位符。所以,如果你有......
List('c','q','y').foldLeft( //....etc.
...然后A
成为Char
的引用,因为该列表是List[Char]
。
B
是foldLeft
必须处理的第二种类型的占位符。具体来说,它是第一个参数的类型以及foldLeft
结果的类型。大多数情况下,当调用foldLeft
时,您实际上不需要指定它,因为编译器会推断它。所以,是的,它可能是......
numbers.foldLeft[Int](0)((m, n) => m + n)
...但为什么要这么麻烦?编译器知道它是一个Int
,读取它的人也是如此(任何知道Scala的人)。
(B, A) => B
是一个函数,它接受2个参数,一个类型为B
,另一个类型为A
,并生成类型为B
的结果。
答案 1 :(得分:2)
方括号中的
[B]
是什么?
一个类型参数(也称为"泛型"如果你以前见过像Java这样的东西)
为什么它在括号中?
因为类型参数是用括号括起来的,所以只是Scala语法。 Java,C#,Rust,C ++使用尖括号< >
用于类似目的,但由于Scala中的数组被访问为arr(idx)
,并且(与Haskell或Python不同)Scala不使用[ ... ]
列表推导,方括号可以用于类型参数,并且不需要尖括号(无论如何都难以解析,特别是在允许中缀和后缀运算符几乎任意名称的语言中)。
冒号之后的
B
是返回类型吗?
右。
什么类型?
同上。返回类型为B
。
看起来这个方法有2个参数列表:一个参数名为
z
,另一个参数名为op
,是一个函数。
此方法具有类型参数B
和值参数的两个参数列表,正确。这样做是为了简化类型推断:类型B
可以从第一个参数z
推断出来,所以在写下op
的lambda表达式时不必重复它。如果z
和op
位于相同的参数列表中,这将无效。
op
看起来需要一个函数(B, A) => B
。
参数op
的类型是(B, A) => B
,即Function2[B, A, B]
,一个带B
和A
并返回{的函数{1}}。
右侧是什么意思?它返回
B
?
是
发生了什么事?
B
充当累加器,m
是列表的当前元素。折叠以整数值n
开始,然后从左到右累积,将所有数字相加。您可以写0
而不是(m, n) => m + n
。
为什么调用时不需要[
_ + _
]?
从B
的类型推断出来。在许多其他情况下,无法自动推断泛型类型,那么您必须通过将其作为方括号中的参数传递来明确指定返回类型。
答案 2 :(得分:0)
这就是所谓的多态性。该函数可以在多种类型上工作,有时您希望提供一个参数,说明将使用哪种类型。基本上B是一个类型参数,可以明确地作为一个类型给出,它应该是Int
,然后它应该用方括号给出,或隐含在括号中,就像你使用0
一样。阅读这里的多态性Scala polymorphism