不能使用 if/when 赋值给带有推断参数的 return lambda,但可以使用 if/when 块

Can't use if/when assignment to return lambda with inferred parameter but can use if/when blocks

我有函数 return 使用 if 语句根据输入 String 条件计算 lambda,它工作正常 - 使用 Head First Kotlin 中的这个修改示例:

fun getConversionLambda(str: String): (Double) -> Double {
    if (str == "CelsiusToFahrenheit")
        return { it * 1.8 + 32 }
    if (str == "KgToPounds")
        return { it * 2.204623 }
    return { it }
}

但由于那显然是使用 when 的好地方,而且我使用 <function declaration> = <expression> 格式,包括 return 类型,然后在编译或预编译时,我收到 Unresolved reference: it 错误:

fun getConversionLambda2(str: String): (Double) -> Double = when(str) {
    "CelsiusToFahrenheit" -> { it * 1.8 + 32 }
    "KgToPounds" -> { it * 2.204623 }
    else -> { it }
}

即使我在函数块中将其指定为 return 的结果,或者先将其分配给变量然后 return,我仍然会收到 Unresolved reference 错误:

fun getConversionLambda3(str: String): (Double) -> Double {
    return when (str) {
        "CelsiusToFahrenheit" -> { it * 1.8 + 32 }
        "KgToPounds" -> { it * 2.204623 }
        else -> { it }
    }
}

唯一能让它工作的方法是在 lambda 中指定 lambda 的输入变量类型:

// and infers the `(Double) -> Double` return type correctly if removed
fun getConversionLambda4(str: String): (Double) -> Double = when(str) {
    "CelsiusToFahrenheit" -> { x: Double -> x * 1.8 + 32 }
    "KgToPounds" -> { x: Double -> x * 2.204623 }
    else -> { x: Double -> x }
}

(我的main:)

fun main(args: Array<String>) {
    println("getCL: ${getConversionLambda("KgToPounds")(2.5)}")
//    println("getCL2: ${getConversionLambda2("KgToPounds")(2.5)}")
//    println("getCL3: ${getConversionLambda3("KgToPounds")(2.5)}")
    println("getCL4: ${getConversionLambda4("KgToPounds")(2.5)}")
    
}

为什么if版本的it没有问题?它显然是在推断 lambda 的参数类型,并根据 getConversionLambda 定义的显式 return 类型执行单参数-it。那么为什么不使用 when-版本 2 和 3?我正在使用 Kotlin v1.4.32。

编辑: 似乎 ifwhen 的任何 'expression assignment' 版本都产生了这个问题 除非我明确指定 lambda 的参数类型:

// Unresolved reference: it
fun getConversionLambda1A(str: String): (Double) -> Double =
    if (str == "KgToPounds") { it * 2.204623 } else { it }

// Unresolved reference: it
fun getConversionLambda1B(str: String): (Double) -> Double {
    return if (str == "KgToPounds") { it * 2.204623 } else { it }
}

但这两个指定了 lambda 参数的版本不会产生错误:

// works
fun getConversionLambda1Aokay(str: String) =
    if (str == "KgToPounds") { x: Double -> x * 2.204623 } else { x: Double -> x }

// works
fun getConversionLambda1Bokay(str: String): (Double) -> Double {
    return if (str == "KgToPounds") { x: Double -> x * 2.204623 } else { x: Double -> x }
}

问题是您在尝试引用“它”时不在传入函数的范围内。只需添加大括号即可。

fun getConversionLambda1A(str: String): (Double) -> Double =
if (str == "KgToPounds") { { it * 2.204623 } } else { { it } }

fun getConversionLambda2(str: String): (Double) -> Double = when(str) {
"CelsiusToFahrenheit" -> {{ it * 1.8 + 32 }}
"KgToPounds" -> {{ it * 2.204623 }}
else -> {{ it }} }