Education logo

Kotlin’s High-Flying High-Order Functions

Learn how to use high-order functions in Kotlin for Android dev. Discover the power of functional programming and avoid code duplication

By Alparslan Selçuk DevelioğluPublished 5 days ago 4 min read
Image designed by Author on Canva

In the world of functional programming, functions get the VIP treatment - they're considered just as crucial as other types like Strings or Integers. What's cool is that you can actually pass functions around just like you would with a String or an Integer. This opens up possibilities where functions can receive other functions as parameters or even return them.

Take Kotlin, for example. Unlike Java, Kotlin doesn't force functions to be tied down inside classes. This freedom allows for what we call high-level functions. These are essentially functions that can manipulate or produce other functions, which can really help streamline some of the more complex coding tasks. It's a natural fit for Kotlin and something that sets it apart in functional programming. Plus, you can stash functions in data structures and variables, treating them like any regular piece of data.

Let me show you why higher-order functions are a big deal in Kotlin. I'll start with a straightforward example to break it down, and then I'll demonstrate how this can be super useful in Android development. Ready to dive in? Here's a basic way to set up a function that can take another function as a parameter:

fun passMeFunction (text: String, function: ( ) -> Unit) {

// do something execute the function

function()

}

passMeFunction ( "text" ) { print ( it ) }

passMeFunction ( "text" ) { s -> print ( s ) }

passMeFunction ( "text" , { print ( it ) } )

passMeFunction ( "text" , { s -> print ( s ) } )

passMeFunction ("text", ::print ) // KISS : Keep It Small Stupid

Honestly, I didn't even realize I needed this feature until I started using it. Once I began, I understood that I could use higher-order functions in many places. Especially when writing a project of medium or larger scale, you often need the same piece of code in other Activities, Fragments, and classes. For example, the action of deleting a user can be performed both from the user list and the user detail page. However, if you start copy-pasting, as the project progresses, you might drown in a sea of redundant code, produce junk code, and make code management unnecessarily difficult.

Coming to a real-life example:

At Peakup, we developed an Android app known as Leave Management. It's designed to let employees swiftly request and monitor their leaves while giving team leaders and HR staff a straightforward way to handle everything. During the development of this app, I ran into an issue:

I realized I was writing nearly the same function for deleting, approving, and rejecting leaves, resulting in unnecessary code repetition. In all three operations, I would first close the leave detail DialogFragment, then display a dialog asking, "Are you sure you want to delete/reject/approve?" When the user touched the confirm button, I would send a request to the backend via the respective function. When I noticed the redundant code, the Higher Order Function feature came to mind because only the text in the Dialog and the request function called were different in the three functions. I wrote the following function:

private fun showAlertAndOperate(@StringRes stringId: Int, leave: Leave, func: () -> Unit) {

leaveDetailsDialogFragment.dismiss()

val text = getString(stringId, leave.User.getNameSurname())

showAlertDialog(text, DialogInterface.OnClickListener {_, which ->

if (which == DialogInterface.BUTTON_POSITIVE) {

func() /* func() is sent as parameter. When dialog shows up

and user tap OK button, func() is fired here */

}

})

}

The function I named 'showAlertAndOperate' takes three parameters. The first parameter is an Int but has a StringRes annotation, meaning the first parameter you send to this function will be a string ID like R.string.xxx. The second parameter is a Leave POJO object. The last parameter is the function that will perform the operation; for instance, if the operation is to delete a leave, the leave deletion request function will be called, and if the operation is to approve a leave, the approval request function will be called.

The 'showAlertAndOperate' function first closes the leave detail dialog fragment. Then, it prepares the text to be displayed in a normal Dialog using the StringRes and Leave parameters. It then sends this text to the showAlertDialog function, triggering the display of the Global alert dialog. When the dialog's confirm button is pressed, the function passed as a parameter to 'showAlertAndOperate' is executed.

override fun onLeaveApprove(leave: Leave) =

showAlertAndOperate(R.string.are_you_sure_to_accept, leave) {

confirmLeave(leave, MODE_ACCEPTED)

}

override fun onLeaveDecline(leave: Leave) =

showAlertAndOperate(R.string.are_you_sure_to_decline, leave) {

confirmLeave(leave, MODE_DECLINED)

}

override fun onLeaveDelete(leave: Leave) =

showAlertAndOperate(R.string.are_you_sure_to_remove, leave) {

deleteLeave(leave)

}

The functions you see above are callbacks that operate in the button onClick event within the interface belonging to the leave detail dialog fragment. As you can see; in onLeaveApprove, the confirmLeave function is called in 'accepted' mode, and in onLeaveDecline, the confirmLeave function is called in 'declined' mode. In onDelete, the deleteLeave() function is called. In the showAlertAndOperate function, these functions will be called instead of the specified func().

Of course, there are many different methods to avoid copy-pasting code. In this article, I only discussed one of these methods. I do not claim it is the 'best method' or a 'golden key'; I just chose it this time and wanted to share it with you.

This article was actually previously published on the blog of a company I used to work for, Peakup in Turkish. I chose to transfer it here because the screenshots were corrupted there, and it was not clear that I was the author.

The original version of this article is published on Medium

I wish you many code-rich days.

coursesVocalhow to

About the Creator

Alparslan Selçuk Develioğlu

8+ years experienced Android Dev. Freshly a Software Team Leader. Colorful, confident personality, a fan of science fiction and fantasy works. An Ultratrail runner who runs in races 60+ kms

Enjoyed the story?
Support the Creator.

Subscribe for free to receive all their stories in your feed. You could also pledge your support or give them a one-off tip, letting them know you appreciate their work.

Subscribe For Free

Reader insights

Be the first to share your insights about this piece.

How does it work?

Add your insights

Comments

There are no comments for this story

Be the first to respond and start the conversation.

    Alparslan Selçuk DevelioğluWritten by Alparslan Selçuk Develioğlu

    Find us on social media

    Miscellaneous links

    • Explore
    • Contact
    • Privacy Policy
    • Terms of Use
    • Support

    © 2024 Creatd, Inc. All Rights Reserved.