是否有可能使用具有可选参数的高阶函数
我把一个虚拟问题放在一起来说明我的观点:假设我们有以下方便的函数来显示有关特定排序算法的信息:
fun sort(name: String, array: Array<Int>, sortingAlgorithm: (Array<Int>) -> Array<Int>) { println(name) sortingAlgorithm(array).forEach { print(" $it ") } println() }
你会这样使用它:
sort("Selection Sort - Θ(n^2)", arrayOf(2, 3, 1), ::selectionSort)
这是因为selectionSort
的签名很简单: fun selectionSort(array: Array<Int>): Array<Int> {
但是,说我有另一个排序算法与以下签名
fun quickSort(array: Array<Int>, start: Int = 0, end: Int = array.size - 1): Array<Int> {
最后两个参数是可选的,所以理论上你可以像调用quickSort
一样调用quickSort
。 也就是说,它遵守签名(Array<Int>) -> Array<Int>
Right?
不幸的是,当我尝试调用sort("Quick Sort", arrayOf(2, 3, 1), ::quickSort)
我得到:
我认为编译器没有足够的智能来认识到这两个参数是可选的。 如何避免这个问题,除了重载sort
方法来接受带签名的高阶函数呢?
有没有避免这个问题,因为它会克服Kotlin类型系统的两个角落石头:
- 1)每个表达式都有一个类型(强类型)
- 2)接收方不影响表达式的类型(本地推理)
例如,如果你可以做到这一点,以下将无法工作,这是你的例子的一个简单的重构:
val algorithm = ::quickSort sort("Quick Sort", arrayOf(2, 3, 1), algorithm)
无论如何, sort("Quick Sort", { quickSort(unsorted) })
解决方法对于Kotlin开发人员来说花费时间在这个问题上太简单了。