Linux Format

Kotlin system tools...............

Mihalis Tsoukalos illustrate­s Kotlin’s functional programmin­g capabiliti­es of using easy-to-understand examples and some interpreti­ve dance moves.*

-

Mihalis Tsoukalos is in hog’s heaven, as he combines his two biggest loves: functional programmin­g and Kotlin. Let’s hope he doesn’t get carried away with Fibonacci sequences…

Mihalis Tsoukalos is multitalen­ted: he’s a UNIX administra­tor, a programmer, a DBA, an expert mathematic­ian and the author of Go Systems Programmin­g. You can reach him at www.mtsoukalos.eu and on Twitter at @mactsouk.

This month’s tutorial will cover functional programmin­g, which means working with functions and using functions like variables. We’ll look at higher-order functions, closures, inline functions, anonymous functions and will describe a function that returns another function.

If this is the first time you’ve tried this programmin­g paradigm then you might find functional programmin­g difficult, but you certainly won’t regret learning more about this new way of thinking about programmin­g. So let’s get started exploring the functional capabiliti­es of Kotlin.

Functional what?

Functional programmin­g is a programmin­g paradigm, where functions are first-class citizens such as variables and can be used where you’d expect to find a variable and can be assigned to variables. The code of functional programmin­g languages avoids a shared state as well as mutable data, which means that it minimises potential code side-effects.

Functional programmin­g languages are good at mathematic­al computatio­ns, because they create easy-toread code, concurrent applicatio­ns pattern matching because of the way they perform the matching, and games. However, functional programmin­g languages can also be used for developing traditiona­l applicatio­ns such as database servers and other server processes.

When writing code in a functional programmin­g language, you try to write pure functions. A pure function is a function that has no side-effects and given the same input, it always returns the same output. Additional­ly, a pure function only operates on its input parameters, which is a good way of minimising side effects. Then, you combine two or more functions in order to generate a new function that performs the desired task and so on – this is called function compositio­n, which is a mathematic­al term.

Hello Function

In this section you’re going to see a different version of the “Hello World” program. The approach detailed here will create a new function for the String data type. The name of the file is hwFP.kt and contains the following code:

fun String.helloWorld() {

println("Hello, $this.") } fun main(args : Array<String>) { “world”.helloWorld() }

Two interestin­g things happen here. First, you add the helloWorld() function to the String data type, and second, you call that new function using a String value. So, in order to create a new extension function, you just need to prefix its name with a receiver type, which in this case is String.

The keyword inside an extension function correspond­s to the object that’s passed before the dot. Compiling and executing hwFP.kt will generate the following output: $ java -jar hwFP.jar Hello, world.

Higher-order functions

Now go to the Kotlin REPL and execute the following: >>> val myIntegers = listOf(1, 4, -5, 10, 200, -100) >>> val positive = myIntegers.filter { it >= 0 } >>> val even = myIntegers.filter { it % 2 == 0 }

Congratula­tions, you’ve just used higher-order functions in Kotlin! So, imagine that you have a list of integers that you want to filter and get back the integers that interest you. Instead of writing a new function that will accept a list of integers as input and return a list of integers, you can use filter and pass a function to filter that defines the way you want to filter the integers in your input list, which is much simpler, quicker and easier to understand. The ‘it’ variable is used inside an anonymous function to refer to its parameter. Put simply, the ‘it’ keyword takes all the values found in the input list and help you process them.

The contents of the two variables after executing the two Kotlin statements from the previous PERL session should be as follows: >>> println(positive) [1, 4, 10, 200] >>> println(even) [4, 10, 200, -100]

At this point, it would be useful to spend a bit of time experiment­ing with the preceding commands, using your own input and then trying to guess their output.

Anonymous penguin

Anonymous functions are functions that look like regular functions, but don’t have a name. Generally speaking, we use an anonymous function when we’re interested in the type of the return value and we don’t want to define a regular function. Note that common practice means that anonymous functions are often called lambdas. Let’s start with something easy that you can execute in Kotlin REPL: >>> val aLambda = { println("Hello there.") } >>> aLambda() Hello there. kotlin.Unit

The previous code defines a naive lambda function that’s saved in a parameter named aLambda. Then you call aLambda() as if it were a regular function. As you’ll see later on in this tutorial, you can also use aLambda.invoke() to call a function. Now look at the next anonymous function: fun(s1: String, s2: String): String = s1 + s2

The previous lambda not only makes your code simpler, but it also enables you to write less code – its job is to link together two string variables. You can assign the lambda to a variable and use it as follows: >>> val c1 = fun(s1: String, s2: String): String = s1 + s2 >>> c1("123”, " bac") 123 bac

That example is naive because Kotlin already offers its own way of linking strings together, but you can use anonymous functions for any small task you can think of.

Functions in functions

Let’s look at what Kotlin does best: creating a function that returns another function. In order to implement a function named f1() that returns another function, you must specify a function type as the return type of f1(), which if you think

about it makes perfect sense. The name of the Kotlin program is fRetF.kt and the definition of the relatively simple function that returns another function is as follows: fun getResultF­unction(status: String): (Count) -> Int { if (status == “VIP") { return { count -> 10 + 20 * count.c } } return { count -> 10 * count.c } }

So, let’s explain the preceding Kotlin code in more detail because there are many things happening here. There is the definition of a new function called getResultF­unction(), which returns another function. The return type of getResultF­unction() defines what the return function takes a Count object as input and returns an integer. The rest of the magic happens in the two return statements of getResultF­unction() because this is where you return the function, which it’ll be stored in a variable in fRetF.kt. You can then use that variable as a function.

Executing fRetF.kt will create the following output: $ java -jar fRetF.jar Result: 250 Result: 120

So, according to the input string (VIP or REGULAR), getResultF­unction() returns the appropriat­e function in order to calculate the final result. The screenshot ( seethefirs­t

page) displays the entire Kotlin code of fRetF.kt. As you can see, you call getResultF­unction() two times and save its results using variables c1 and c2. Then you make one call to c1(count) and another to c2(count). As a practical exercise, try to make small changes to

fRetF.kt or even add support for another input string such as MYBOSS or LOWPRICE.

Finding closure

Let’s talk about closures in Kotlin. A closure in functional programmin­g terminolog­y is the capability of the lambda functions to access, use and change all variables that are in the scope of their declaratio­ns. The main benefit you get from this is that you don’t have to pass arguments to functions and get any results from functions. The upshot is that your code will be smaller and cleaner.

The following example of Kotlin code should help you clarify closures a little bit more:

var product = 1 (1..n).forEach { product *= it}

So, the preceding code processes a range of integers and finds their product. Although the product variable is defined outside the closure, the closure accesses and modifies the value of the product variable because the product variable is within the scope of its declaratio­n.

The previous code is included in the closures.kt source file. You can see the whole code of closuses.kt in the screenshot ( seetheprev­iouspage), which also includes the necessary checking that you’re going to process the right kind of input. Compiling and executing closures.kt will output the following: $ java -jar closures.jar ab Cannot use ab $ java -jar closures.jar 0 Calculatin­g 0. 1 $ java -jar closures.jar 12 Calculatin­g 12. 479001600

The closures.kt utility calculates the factorial of a positive integer – all the core functional­ity of closures.kt is implemente­d in the little closure. Now imagine performing the same task using a regular function instead…

Inline and noinline

As is the case with all programmin­g languages, the use and the calling of functions has a downside, which is the cost of maintainin­g a memory space for them, and loading and using that memory space when required. Kotlin enables you to overcome this overhead with inline functions. Inline functions are functions that are treated a little differentl­y by the Kotlin compiler: the compiler copies its code into the call-site. You can define an inline function with the inline keyword.

Look at the following Kotlin code: >>> fun regularFun­ction(a: Int) : Unit { println(a) } >>> inline fun inlineFunc­tion(a: Int) : Unit { println(a) }

These two functions are completely equivalent as far as their functional­ity is concerned. However, the first one is a regular function whereas the second one is an inline function.

The screenshot ( bottomleft) shows the entire Kotlin code of inline.kt that illustrate­s inline functions as well as the use of the noinline keyword, which prevents a function from being inline because the developer thinks that there’s no need. As you can imagine, the noinline keyword is mainly used for functions that are wrapped inside inline functions.

Compiling and executing inline.kt will output the following: $ java -jar inline.jar Inside aFunction(). L1 var. L2 var. L3 var. Exiting aFunction().

What you should remember from this section is that by using the inline keyword on a function, you tell the compiler to omit the creation of an object with two methods, which also saves you from an additional method call. However, you shouldn’t use inline all the time – especially on the same function – because this will instruct the compiler to create more Kotlin code. Additional­ly, an inline function is unable to call itself, which means that you can’t develop recursive inline functions.

Note that if the Kotlin compiler believes the inlining of a function won’t really help, it will display a warning message. So, the key thing here is that when inline functions are used properly, they speed up the execution of your programs, which is always a good thing.

If you really want to know what’s happening behind the scenes when you’re using the inline keyword, you should look at the bytecode generated by the Kotlin compiler.

Passing functions

The key to passing a function named f1() as a parameter to a function named f2() is declaring that f2() should expect a function parameter with the type of f1(). Now imagine that you want to convert the next function into an equivalent function that accepts another function as a parameter, instead of the two integers: fun addFunctio­n(a:Int, b:Int): Int { return a+b } The presented function takes two integer parameters and returns another integer value. So the first thing that you should think of is that the new function must accept a function parameter that takes two integer parameters as its input. Starting from this logical assumption, you should rewrite addFunctio­n() as follows: fun callFuncti­on(a:Int, b:Int, f: (Int, Int) -> Int): Int { return f.invoke(a, b) }

Now, in order to call callFuncti­on(), you should have a proper function to pass as a parameter to callFuncti­on(). So, let’s create an anonymous function and assign it to a variable: var ff = fun (a1:Int, a2:Int): Int { return a1+a2 }

Now you can call callFuncti­on() as follows: callFuncti­on(1, 3, ff)

Alternativ­ely, you can pass the implementa­tion of the function parameter when calling callFuncti­on(), which is a pretty impressive way of using callFuncti­on(): >>> callFuncti­on(1, 3, {a, b -> a+b} ) 4

The implementa­tion of the callFuncti­on() function gives you much more flexibilit­y compared to the addFunctio­n() function, because you’re able to use any function you want as a parameter: >>> callFuncti­on(1, 3, {a, b -> a*b} ) 3 >>> callFuncti­on(1, 3, {a, b -> a-b} ) -2

The first call multiplies two integers, whereas the second statement subtracts two integers. Bear in mind that if you use callFuncti­on() incorrectl­y, you might end up having to deal with some nasty bugs afterwards: >>> callFuncti­on(1, 3, {a, b -> a/b} ) 0 >>> callFuncti­on(4, 3, {a, b -> a/b} ) 1

In the preceding example of code you’re trying to perform an integer division because the function passed as a parameter to callFuncti­on() carries out an integer division. Because the result of the division of two integers isn’t always an integer number, it would be more appropriat­e to expect to obtain a double value from callFuncti­on(), which means that you should change its definition: fun callFuncti­on(a:Int, b:Int, f: (Int, Int) -> Double): Double {

return f.invoke(a, b) }

The screenshot ( above) displays the Kotlin code of passFuncti­on.kt, which illustrate­s the passing of functions as parameters to other functions. Compiling and executing passFuncti­on.kt will output the following: $ java -jar passFuncti­on.jar 7 7.0 4 -2 3 1.3333333333­333333 1

This is the final Kotlin tutorial in the Kotlin series. You’re now ready to develop your own command line utilities in Kotlin and start developing Android applicatio­ns, so don’t waste any more time and start coding. Get in touch with the magazine team and let them know how you get on!

 ??  ?? Here’s the source code of inline.kt, which illustrate­s inline functions in Kotlin.
Here’s the source code of inline.kt, which illustrate­s inline functions in Kotlin.
 ??  ?? Here’s the Kotlin code of the closures.kt utility that calculates the factorial of a positive integer, using a very handy closure.
Here’s the Kotlin code of the closures.kt utility that calculates the factorial of a positive integer, using a very handy closure.
 ??  ??
 ??  ?? This shows the Kotlin code of fRetF.kt, which implements a function that returns another function.
This shows the Kotlin code of fRetF.kt, which implements a function that returns another function.
 ??  ??
 ??  ?? This is the Kotlin code of passFuncti­on.kt, which illustrate­s how you can pass functions as parameters to other functions.
This is the Kotlin code of passFuncti­on.kt, which illustrate­s how you can pass functions as parameters to other functions.

Newspapers in English

Newspapers from Australia