Home

Playing with Kotlin Higher Order Functions

Ported from Medium, original source here

One of the cool things in Kotlin is having ability to pass around functions as objects. That’s where higher order functions come and allow us to write code more declaratively.

I’m gonna list down some function blocks

Let’s start with basic ones

We often run into scenarios where we encapsulate logic inside try/catch block but just log the exception in catch block. Sometimes even the catch seems useless, so…

inline fun <T> justTry(block: () -> T) = try { block() } catch (e: Throwable) {}


And now we just forget the catch block

justTry {
    myFunctionWhichMayFail()
}


Similarly

inline fun debugMode(block : () -> Unit) {
    if (BuildConfig.DEBUG) {
        block()
    }
}

inline fun lollipopAndAbove(block : () -> Unit) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        block()
    }
}

inline fun Context.withNetwork(block: () -> Unit) {
    val connectivityManager = this.getSystemService(Context.CONNECTIVITY_SERVICE) as?  ConnectivityManager
    connectivityManager?.let {
        val netInfo = it.activeNetworkInfo
        netInfo?.let {
            if (netInfo.isConnected) {
                block()
            }
        }
    }
}

transforms to

debugMode {
    StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
            .detectAll()
            .penaltyLog()
            .build())
}

lollipopAndAbove {
    view.elevation = 1.0f
}

withNetwork {
    // make network request
}

Again, this makes code more readable and looks nice :)

But one should consider the logic which should be transformed into function block. The above code block only has if condition which works fine but if there needs to be an else section, we may wanna avoid function blocks. This is valid for withConnection {} where an else case may be required to show some message for network connectivity.

Moving on to more cool stuff

fun <T> asyncRxExecutor(heavyFunction: () -> T, response : (response : T?) -> Unit) {
val observable = Single.create<T>({e ->
    e.onSuccess(heavyFunction())
})
observable.subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe { t: T? ->
            response(t)
        }
}

The above code is a generic function which accepts a function as a first parameter, executes using RxJava observable in a new thread and then sends back response exposed as a lambda. Here is a sample usage

asyncRxExecutor({ myHeavyFunction() }, { response ->
    println(response.toString())
})

So basically we took an arbitrary function which was already written or may be written in future , did it’s execution asynchronously and returned a result.

We could use different mechanism for async execution like Kotlin Coroutines

fun <T> asyncCoroutinesExecutor(heavyFunction: () -> T, response : (response : T?) -> Unit) {
    async(UI) {
        val data : Deferred<T> = bg {
            heavyFunction()
        }
        response(data.await())
    }
}

asyncCoroutinesExecutor({ myHeavyFunction() }, { response ->
    println(response.toString())
})

We can similarly create an executor for running code on ui thread.

inline fun uiThreadExecutor(crossinline block: () -> Unit) {
    val mainHandler = Handler(Looper.getMainLooper())
    mainHandler.post{
        block()
    }
}

and…

thread {
    myHeavyFunction()
    uiThreadExecutor {
        view.text = "Just updating"
    }
    myAnotherHeavyFunction()
}

thread {} is provided by Kotlin itself for running code in a thread.

This is just the tip of the iceberg of what we can do with higher order functions! I’m maintaining a repo where I add utilities like this. Have a look

jitinsharma/Kotlin.someExtensions