Kotlin:将运算符作为函数参数传递

8
我在 Kotlin 中有以下函数。
fun evaluate(first:Int?, second:Int?) {
    var result = 0
    if (v.equals('*')) {
        result = (first ?: 0) * (second ?: 0)
    } else if (v.equals('+')) {
        result = (first ?: 0) + (second ?: 0)
    } else if (v.equals('-')) {
        result = (first ?: 0) - (second ?: 0)
    } else if (v.equals('/')) {
        result = (first ?: 0) / (second ?: 0)
    }
    return result   
}

我希望以这种方式进行更改,以便我可以将所需的操作符作为第三个参数传递并评估表达式。类似于
fun evaluate(first:Int?, second:Int?, op: () -> Unit):Int {
    return (first ?: 0).op(second ?: 0)
}

在这种情况下,我如何将运算符作为函数传递?我查看了一个类似的问题,但是不清楚如何使用运算符来实现。


你想要摆脱 if 条件吗?'v' 是从哪里来的? - ilya.dorofeev
@ilya.dorofeev 展示了最终预期的函数,可以摆脱所有 if 条件。 - Jayson Minard
3个回答

12
写一个高阶函数,使用一个函数类型作为参数,可以同时使用内置运算符和lambda表达式进行操作,代码如下:

higher order function

function type

lambda expressions

fun evaluate(first: Int?, second: Int?, op: (Int, Int) -> Int): Int {
    return op(first ?: 0, second ?: 0)
} 

可以使用内置运算符进行调用,例如:

val r1 = evaluate(value1, value2, Int::times) 
val r2 = evaluate(value1, value2, Int::plus)
val r3 = evaluate(value1, value2, Int::minus) 
val r4 = evaluate(value1, value2, Int::div) 

并且使用自定义函数:

val r5 = evaluate(value1, value2) { a, b -> (a * a) + b }

现在,您也可以将运算符分配给变量,例如您的v
val v: (Int, Int)->Int = Int::times  // typing needed on left to avoid ambiguous alternatives
// and then later...
val r6 = evaluate(value1, value2, v) 

请注意,为签名Int.(Int)->Int编写的函数可以传递到期望(Int, Int)->Int参数的参数中,因为接收器this将作为第一个参数传递。

1
这也可以:evaluate2(value1, value2, Int::times),所以你不需要一个单独的函数,只需要最后一个。 - voddan
有趣的是签名不匹配,但由于接收器是第一个参数,所以它仍然有效。很酷。这是故意的还是一个错误? - Jayson Minard
确认这是有意的,将更新答案,谢谢 @voddan - Jayson Minard
这是一个1.0版本之前的功能。 - voddan

1
() -> Unit更改为Int.(Int) -> Int。然后,所有其他代码都应该按照你在那里编写的方式工作。
在调用方面,this是第一个整数,第一个参数是第二个整数:{ other -> this * other }

0

你可以尝试这样做:

fun evaluate(first: Int?, second: Int? , v:String ): Int = v.op(first ?: 0, second ?: 0)

fun String.op(first:Int,second:Int):Int = when (this) {
    "*" -> first * second
    "+" -> first + second
//....
    else -> throw Exception()
}       
fun main(args: Array<String>) {
    println(evaluate(2,3,"*"))
    println(evaluate(2,3,"+"))
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接