在应用程序之前选择函数引用:类型推断问题
Selecting function reference before application: problem with type inference
我想在将其应用于参数之前选择函数引用,但 Kotlin 无法推断其类型。
假设我有一个 class
class Circle(val radius: Float)
和一个函数
fun sortByRadius(circles: MutableList<Circle>, ascending: Boolean) {
if (ascending)
circles.sortBy { it.radius }
else
circles.sortByDescending { it.radius }
}
我也想把这个函数体重写成这样:
circles.(
if (ascending) MutableList<Circle>::sortBy
else MutableList<Circle>::sortByDescending
) { it.radius }
但它不起作用。
我还发现
(MutableList<Circle>::sortBy)(circles) { it.radius }
almost 有效,Kotlin 无法推断出 Float
类型的半径;所以我想知道如何指定它。然后我们可以写
(if (ascending) MutableList<Circle>::sortBy
else MutableList<Circle>::sortByDescending)(circles) { it.radius }
不知道我是否完全理解你的意思,但这里是我为你的案例写的:
fun main() {
val circles = mutableListOf(
Circle(.1f), Circle(.5f), Circle(3f)
)
val sortBy: (MutableList<Circle>, selector: (Circle) -> Float) -> Unit = { list, selector ->
list.sortBy(selector)
}
val sortByDescending: (MutableList<Circle>, selector: (Circle) -> Float) -> Unit = { list, selector ->
list.sortByDescending(selector)
}
val ascending = false
(if (ascending) sortBy else sortByDescending)(circles) {
it.radius
}
// Or maybe more clear way
//(if (ascending) sortBy else sortByDescending).invoke(circles) {
// it.radius
//}
}
希望对您有所帮助。
问得好,但似乎不可能(使用函数引用)。我试图明确指定预期类型:
val f: MutableList<Circle>.((Circle) -> Float) -> Unit =
if (ascending) MutableList<Circle>::sortBy else MutableList<Circle>::sortByDescending
但错误消息显示
Type inference failed. Please try to specify type arguments explicitly.
并且the grammar不允许:
callableReference
: (receiverType? '::' (simpleIdentifier | 'class'))
;
即::
后面只能跟一个标识符或 class
。这是一个奇怪的漏洞,因为 Java 语法确实允许在方法名称之前使用类型参数。
绑定引用也无济于事:
(circles::sortBy) { it.radius } // doesn't compile
甚至显式类型都不起作用,这让我很惊讶:
val f: ((Circle) -> Float) -> Unit = circles::sortBy
但这确实:
val f: ((Circle) -> Float) -> Unit = { circles.sortBy(it) }
所以最终你可以写(需要在 lambda 周围加上括号)
val f: ((Circle) -> Float) -> Unit =
if (ascending) ({ circles.sortBy(it) }) else ({ circles.sortByDescending(it) })
f { it.radius }
但可能不想!
我想在将其应用于参数之前选择函数引用,但 Kotlin 无法推断其类型。
假设我有一个 class
class Circle(val radius: Float)
和一个函数
fun sortByRadius(circles: MutableList<Circle>, ascending: Boolean) {
if (ascending)
circles.sortBy { it.radius }
else
circles.sortByDescending { it.radius }
}
我也想把这个函数体重写成这样:
circles.(
if (ascending) MutableList<Circle>::sortBy
else MutableList<Circle>::sortByDescending
) { it.radius }
但它不起作用。 我还发现
(MutableList<Circle>::sortBy)(circles) { it.radius }
almost 有效,Kotlin 无法推断出 Float
类型的半径;所以我想知道如何指定它。然后我们可以写
(if (ascending) MutableList<Circle>::sortBy
else MutableList<Circle>::sortByDescending)(circles) { it.radius }
不知道我是否完全理解你的意思,但这里是我为你的案例写的:
fun main() {
val circles = mutableListOf(
Circle(.1f), Circle(.5f), Circle(3f)
)
val sortBy: (MutableList<Circle>, selector: (Circle) -> Float) -> Unit = { list, selector ->
list.sortBy(selector)
}
val sortByDescending: (MutableList<Circle>, selector: (Circle) -> Float) -> Unit = { list, selector ->
list.sortByDescending(selector)
}
val ascending = false
(if (ascending) sortBy else sortByDescending)(circles) {
it.radius
}
// Or maybe more clear way
//(if (ascending) sortBy else sortByDescending).invoke(circles) {
// it.radius
//}
}
希望对您有所帮助。
问得好,但似乎不可能(使用函数引用)。我试图明确指定预期类型:
val f: MutableList<Circle>.((Circle) -> Float) -> Unit =
if (ascending) MutableList<Circle>::sortBy else MutableList<Circle>::sortByDescending
但错误消息显示
Type inference failed. Please try to specify type arguments explicitly.
并且the grammar不允许:
callableReference
: (receiverType? '::' (simpleIdentifier | 'class'))
;
即::
后面只能跟一个标识符或 class
。这是一个奇怪的漏洞,因为 Java 语法确实允许在方法名称之前使用类型参数。
绑定引用也无济于事:
(circles::sortBy) { it.radius } // doesn't compile
甚至显式类型都不起作用,这让我很惊讶:
val f: ((Circle) -> Float) -> Unit = circles::sortBy
但这确实:
val f: ((Circle) -> Float) -> Unit = { circles.sortBy(it) }
所以最终你可以写(需要在 lambda 周围加上括号)
val f: ((Circle) -> Float) -> Unit =
if (ascending) ({ circles.sortBy(it) }) else ({ circles.sortByDescending(it) })
f { it.radius }
但可能不想!