Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 在reduce()中使用扩展函数引用_Kotlin - Fatal编程技术网

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)
}