Kotlin Magic Functions — Everything You Need To Know

Mikhail Raevskiy
Aug 27, 2020 · 5 min read

In this article, we’ll take a look at the most common “magic” use of functions in Kotlin.

Kotlin Magic Functions — Everything You Need To Know
Kotlin Magic Functions — Everything You Need To Know
Photo by Louis Tsai on Unsplash

Extension Functions

Let’s start simple: extending classes without inheritance. We can, without changing the class Stringand all the packages that use it, extend this class by adding a new method or property (field). Let's have a method deleteSpaces():

And we can use this method as if it were part of a class String. The user will see it like this:

After compilation, this method will look something like this (part of the code has been simplified to make it easier for you to understand the essence):

From this we can conclude that inside the method deleteSpaces() we have access only to public fields and methods of the class, so that encapsulation is not broken.

In addition to Extension Functions in Kotlin, by analogy, there can be Extension Properties:

Most of the “magic” uses of functions and lambdas in Kotlin, like this one, are nothing more than syntactic sugar, but how convenient!

Lambda functions and anonymous functions

In Kotlin, anonymous and lambda functions are functions without a name, but they can also be used as objects. They can be written directly inside the expression, bypassing a separate declaration.

The syntax for a lambda expression is:

{ arguments -> returned_type
function_body
}

The syntax for declaring an anonymous function is exactly the same as for a regular function, but the first has no name.

We will talk about the semantic differences between these types of functions later, but now we will consider examples of using lambdas together with higher-order functions.

Higher-order functions

A higher-order function is a function that takes as one of its arguments another function, including a lambda or anonymous function. A striking example of using such functions is a callback.

Let’s say we have a higher-order function longWork():

It takes a function as an argument callback(), but only calls it after the function doSomething(). Using this function:

Here we call the function longWork()and pass it a lambda function as an argument, which it will call later. Koltin allows you to put a lambda outside the brackets if it is the last argument of a function, and also completely remove the brackets if the lambda is the only argument. Also, in most cases, you can remove the return type and replace the arguments with _if they are not used. Here's a shorter version:

And this outwardly resembles not a higher-order function, but a language construct, as, for example, synchronizedin Java. By the way, synchronizedin Kotlin it is built exactly as a higher-order function.

This is very convenient for creating so-called DSL (Domain-Specific Languages) — domain-specific languages. Some of the most popular DSLs for Kotlin are Anko (Android UI directly in Kotlin while preserving the convenience of XML markup), Gradle Kotlin DSL (Gradle scripts on Kotlin), kotlinx.html (by analogy with Anko).

For example, consider a Kotlin HTML page:

This will print to stdout:

The main advantage of this DSL is that unlike declarative HTML, Kotlin has variables that can be used to generate a dynamic page. And this is much prettier and more convenient than classical page generation through a concatenation of many strings. In reality, other methods are used to generate HTML markup, this one was shown only as an example of a DSL in Kotlin.

Another example of using higher-order functions is as analogous to the Streams API from Java:

More complex lambdas

Let’s look at some example code:

Using more complex higher-order functions from the language standard library, you can turn the code above into the following:

As you can see, the method apply()allows you not to write several times builder.append()thanks to the following method prototype:

public inline fun <T> T.apply(block: T.() -> Unit): T

Here the lambda function blockis an extension method for the type T, in this case for StringBuilder. And append()inside the lambda block is this.append()where thisis the instance of the class StringBuilder.

The method let()works in a similar way, only accepting a slightly different lambda:

public inline fun <T, R> T.let(block: (T) -> R): R

Here, the object reference is passed not as a quality this, but as an explicit method argument, but we did not specify it. In such cases, the compiler automatically names the first argument to the lambda function "it".

A little about the unsaid

First, Kotlin, unlike Java, has overloaded operators. So, for example, if a class has a method plus(), then it can be called by an operator +, and a method by get()an operator [].

Secondly, functions in Kotlin can be explicitly marked as inlineor noinline. This modifier tells the compiler whether to inline the function to improve performance or not. But here's the catch: different behavior returnin inlineand noinlinefunction.

In inlinefunctions, it returnwill be produced from the closest noinlinefunction in scope . B noinline- from the function itself. Named solutions solve this problem return.

To make returnfrom the lambda that we pass in the example above to apply(), you can use return@apply.

Named can not only be return, but also break, continue. You can also create your own labels:

In addition, there is a function modifier tailrecthat tells the compiler to replace the recursion in the function with a loop if it is written in the return if-then-else functional format. Example:

Thirdly, if a method requires an object as arguments, which must be inherited from a class / interface with one abstract method, then a lambda or an anonymous function can be passed to this function, and the compiler itself will create an anonymous class with overriding the abstract method by our lambda. For example, the Android standard library has a method public void setOnClickListener(View.OnClickListener l)where OnClickListeneris an interface with a single method onClick(View v).

The lambda passed in the view setOnClickListener { doSomething() }will be compiled into an anonymous class that implements the interface OnClickListener, where our lambda will turn into a method onClick(View v).

Outcome

This is far from all about functions in Kotlin, only the most commonly used. With its “magic” functions, Kotlin makes writing and, most importantly, reading code much easier. Ease of writing and safety are two of the most important differences between Kotlin and Java, created back in 1995 (!). At that time, the convenience and safety of the code were only dreamed of.

Read More

If you found this article helpful, click the💚 or 👏 button below or share the article on Facebook so your friends can benefit from it too.

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Sign up for Best Stories

By Dev Genius

The best stories sent monthly to your email. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Mikhail Raevskiy

Written by

Bioinformatician at Oncobox Inc. (@oncobox). Research Associate at Moscow Institute of Physics and Technology (@mipt_eng).

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Mikhail Raevskiy

Written by

Bioinformatician at Oncobox Inc. (@oncobox). Research Associate at Moscow Institute of Physics and Technology (@mipt_eng).

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store