是否可以将高阶函数与可选参数一起使用

FRR*_*FRR 5 kotlin

我提出了一个虚拟问题来说明我的观点:假设我们具有以下方便的功能来显示有关特定排序算法的信息:

fun sort(name: String, array: Array<Int>, sortingAlgorithm: (Array<Int>) -> Array<Int>) {
    println(name)
    sortingAlgorithm(array).forEach { print(" $it ") }
    println()
}
Run Code Online (Sandbox Code Playgroud)

您可以这样使用它:

sort("Selection Sort - ?(n^2)", arrayOf(2, 3, 1), ::selectionSort)
Run Code Online (Sandbox Code Playgroud)

这之所以可行selectionSort是因为的签名很简单:fun selectionSort(array: Array<Int>): Array<Int> {

但是说我还有另一个具有以下签名的排序算法

fun quickSort(array: Array<Int>,
              start: Int = 0,
              end: Int = array.size - 1): Array<Int> {
Run Code Online (Sandbox Code Playgroud)

最后两个参数是可选的,因此从理论上讲,您可以quickSort按相同的方式调用selectionSort。也就是说,它仍然尊重签名(Array<Int>) -> Array<Int>吗?

不幸的是,当我尝试致电时,sort("Quick Sort", arrayOf(2, 3, 1), ::quickSort)我得到:

类型不匹配

我认为编译器不够聪明,无法意识到这两个参数是可选的。除了使sort方法重载以接受带有签名的高阶函数以外,如何避免这个问题?

vod*_*dan 5

无法避免这个问题,因为它会与 Kotlin 类型系统的两个基石相矛盾:

  • 1) 每个表达式都有一个类型(强类型)
  • 2) 接收方不影响表达式的类型(局部推理)

例如,如果您可以这样做,则以下内容将不起作用,这是您示例的简单重构:

val algorithm = ::quickSort
sort("Quick Sort", arrayOf(2, 3, 1), algorithm)
Run Code Online (Sandbox Code Playgroud)

无论如何,sort("Quick Sort", { quickSort(unsorted) })对于 Kotlin 开发人员来说,解决方法太简单了,无法花时间解决这个问题。