Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: Passing operator as a function parameter

Tags:

kotlin

I've the following function in 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   
}

I want to change it in a way so that I can pass as a third parameter needed operator and evalute the expression. Something like

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

How can I pass the operator as a function in this case? I checked the same kind of a question, but it is not clear how you can do that with operator.

like image 821
vtor Avatar asked Sep 13 '16 11:09

vtor


Video Answer


2 Answers

Writing a higher order function using a function type as a parameter allows using both built-in operators and lambda expressions for the operation, so this would look like:

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

Which can be called with built-in operators such as:

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) 

And with custom functions:

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

Now you can also assign the operators to variables, such as you 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) 

Note that a function written for signature Int.(Int)->Int can be passed into a parameter expecting (Int, Int)->Int because the receiver this will be passed in as the first parameter.

like image 140
6 revs Avatar answered Dec 16 '22 00:12

6 revs


Change () -> Unit into Int.(Int) -> Int. Then all the other code should work as you've written it there.

On the calling side it this is the first int, and the first parameter is the second int: { other -> this * other }

like image 34
Kiskae Avatar answered Dec 15 '22 22:12

Kiskae