Kotlin 在reduce()中使用扩展函数引用
假设:Kotlin 在reduce()中使用扩展函数引用,kotlin,Kotlin,假设: val sets = listOf(setOf(1, 2, 3), setOf(2, 3, 4), setOf(3, 4, 5)) 为什么这在Kotlin 1.2中是非法的 val unionOfSets = sets.reduce(Set<Int>::union) // == setOf(1, 2, 3, 4, 5) 发件人: 带接收器和不带接收器的函数类型的非文字值是可互换的,因此接收器可以代替第一个参数,反之亦然。例如,类型为(a,B)->C的值可以在预期为a(B
val sets = listOf(setOf(1, 2, 3), setOf(2, 3, 4), setOf(3, 4, 5))
为什么这在Kotlin 1.2中是非法的
val unionOfSets = sets.reduce(Set<Int>::union) // == setOf(1, 2, 3, 4, 5)
发件人:
带接收器和不带接收器的函数类型的非文字值是可互换的,因此接收器可以代替第一个参数,反之亦然。例如,类型为(a,B)->C的值可以在预期为a(B)->C的位置传递或赋值,反之亦然
Kotlin似乎没有在接收方上成功地进行类型推断,可能是因为所有模板(Kotlin对类型没有任何保证) 但您可以通过将引用传递给invoke callable来解决此问题:
fun main(args: Array<String>) {
val sets = listOf(setOf(1,2,3), setOf(4,5,6), setOf(7,8,9))
val unionOfSets = sets.reduce(Set<Int>::union::invoke)
println(unionOfSets)
}
fun main(args:Array){
val集合=列表集合(集合(1,2,3)、集合(4,5,6)、集合(7,8,9))
val unionOfSets=sets.reduce(Set::union::invoke)
println(联合集合)
}
更新:下面是Set.reduce(Set::union)不起作用的原因
Kotlin使用智能转换来解析接收器(参见第553行)
但是,只有在文档()中提到的类型得到保证的情况下,智能强制转换才能工作:
请注意,当编译器无法保证变量不能在检查和使用之间更改时,智能强制转换不起作用
编译器试图找到正确的接收器(通过智能转换),但无法找到,因为编译器无法保证acc变量不能更改。这是由于嵌套的泛型:您有一个列表
,它将在运行时成为列表
这就是为什么我们可以使用invoke。Invoke是在生成时生成的运算符方法,它是类型安全的(不需要智能转换)。它与
infix
无关,而是与扩展函数本身有关。其他扩展函数也会发生同样的情况。尽管我还没有找到它的源代码,但我相信它与扩展函数在底层的转换方式有关(例如,使用JVM,它们只是静态方法)。有趣的是:如果你做了val func=Set::union;set.reduce(func)
它会工作的。但是Set.reduce(Set::union)
不会。谢谢你@Roland,我根据你的评论澄清并概括了我的问题。
fun main(args: Array<String>) {
val sets = listOf(setOf(1,2,3), setOf(4,5,6), setOf(7,8,9))
val unionOfSets = sets.reduce(Set<Int>::union::invoke)
println(unionOfSets)
}