Kotlin Thursdays - Introduction to Functional Programming in Kotlin Part 1


Resources

Introduction

Welcome to Kotlin Thursdays! This week I’m starting a series on functional programming with Kotlin. Functional programming is something I’m passionate about, and Kotlin has some great functional programming support! Functional programming can lead to code that is easier to think about, has fewer bugs and is easier to test.

What better way to dive into functional programming than to learn about functions! It might help to think of functions as “mini-programs”. Functions allow us to write some code once and then use that code multiple times throughout the rest of our program.



The Main Function

To make a Kotlin program, we need to make a function to “kickstart” our program. This function is called the main function. To create the mainfunction, let’s make a file called FunWithFunctions.kt and write the following code in it:

fun main() {
println(“Hello World!”)
}

We can compile this into a jar file that we can run with the following command on our terminal:

kotlinc-jvm FunWithFunctions.kt -include-runtime -d functions.jar

Then we can run the program with the following command:

java -jar functions.jar

For those not familiar, a jar file is how Java Virtual Machine programs are packaged into programs that we can easily run. Kotlin, like Java, uses the Java Virtual Machine to run.

Kotlin knows that when we run our code, it should start by running the mainfunction. But we can make our own custom functions as well! Let’s write our first custom function in my FunWithFunctions.kt file:

fun myFirstFunction(): String {
return "I made my first Kotlin function!"
}

We’re using the same fun keyword as before, and we’re giving this function the name of myFirstFunction. Notice the : String that comes after the function name; this tells Kotlin that when this function finishes running, it is going to return a String object. If we don’t specify that, Kotlin assumes that our function is returning Unit, which is the same thing as void in Java. Finally, we use the return keyword to return our string.

This new function we’ve created can now be used in the main function of our program. Here’s the final content of the FunWithFunctions.kt file:

fun myFirstFunction(): String {
return "I made my first Kotlin function!"
}
fun main() {
val result = myFirstFunction()
println(result)
}

Now we can compile and run it:

kotlinc-jvm FunWithFunctions.kt -include-runtime -d functions.jar
java -jar functions.jar

Higher Order Functions

Kotlin has support for higher order functions. A function is a higher order function if it can do at least one of the following things:

  • Accept another function as an argument.
  • Return a function.

Passing Functions to Other Functions

Let’s examine passing functions into other functions. First, let’s define a function that returns a String:

fun a(): String {
return "I can haz functionz!"
}

Next, we’ll create a second function that can accept this function as a parameter:

fun b(parameter: () -> String): String {
return parameter()
}

We can call function b, passing in function a in our main function:

fun main() {
println(b(::a))
}

When function b runs, it will take function a as the parameter and execute it, returning the value:

I can haz functionz!

Functions That Return Functions

Let’s talk about the second capability that higher order functions possess: returning other functions. Let’s start off again with our function a from before:

fun a(): String {
return “I can haz functionz!”
}

Next we define a new function c that will return the function a we defined earlier:

fun c(): () -> String {
return ::a
}

Note that function c has a return type of () -> String. This is because c is returning the function a which returns a String. Kotlin, being strongly typed, requires us to match our return types correctly. This is different from dynamically typed languages like Ruby, which do not require types to be specified. This might seem like a nuisance at first, but in future episodes we’ll examine how using a strongly typed language like Kotlin actually helps us prevent bugs in our code by using types.

When the function c executes, it returns the function a, but it does not execute function a. Let’s see what happens when we call this in the main function:

fun main() {
println(c())
}

This will print:

function a (Kotlin reflection is not available)

This is because function a is being directly returned as a function, instead of executing and returning a String type. To make it execute, we would have to add two sets of parentheses in the println statement:

fun main() {
println(c()())
}

Now the function a, which is returned by the function c, will execute and return the String value:

I can haz functionz!

This prints out correctly because now we’re calling c which returns a function, then calling that returned function (c is returning a).

To help clarify what’s going on here, let’s write our main function a different way:

fun main() {
val functionA = c()
println(functionA)
}

Note the lack of parentheses around functionA in the println statement. Kotlin will print this out again:

function a (Kotlin reflection is not available)

We can add parentheses to functionA in the println statement to make functionA execute:

fun main() {
val functionA = c()
println(functionA())
}

Now we get the result we wanted:

I can haz functionz!

Higher order functions are a key component of functional programming, as it allows us to build up our program by connecting functions to functions. In future episodes we’ll start to examine how this becomes useful especially as we later learn about function composition, which allows us to write software that is easier to comprehend.

Join me next week on Kotlin Thursdays when I talk about anonymous functions and lambdas!

Views: 128

Happy 10th year, JCertif!

Notes

Welcome to Codetown!

Codetown is a social network. It's got blogs, forums, groups, personal pages and more! You might think of Codetown as a funky camper van with lots of compartments for your stuff and a great multimedia system, too! Best of all, Codetown has room for all of your friends.

When you create a profile for yourself you get a personal page automatically. That's where you can be creative and do your own thing. People who want to get to know you will click on your name or picture and…
Continue

Created by Michael Levin Dec 18, 2008 at 6:56pm. Last updated by Michael Levin May 4, 2018.

Looking for Jobs or Staff?

Check out the Codetown Jobs group.

 

Enjoy the site? Support Codetown with your donation.



InfoQ Reading List

C++26 Draft Finalized with Static Reflection, Contracts, and Sender/Receiver Types

The next major release of C++ reached an important milestone earlier this month, when the ISO C++ committee froze the feature set that will go into C++26. Notable additions include compile-time reflection, contracts, asynchronous execution, and many others.

By Sergio De Simone

Presentation: Continuous Delivery Is Not Possible Without Pair Programming: Lessons From SpareBank 1 and SINTEF in Norway

Asgaut Mjølne Söderbom and Ola Hast unravel the powerful synergy between pair programming and continuous delivery. They explain how this shift allowed their team to abandon traditional hurdles like excessive WIP, lengthy pull requests, and multiple test environments, leading to ultra-fast deployments, superior code quality, and a highly cohesive, efficient engineering team.

By Asgaut Mjølne Söderbom, Ola Hast

AWS Lambda Gains Native Avro and Protobuf Support for Kafka Events with Schema Registry Integration

Lambda now natively supports Apache Avro and Protobuf events, streamlining Kafka event processing - an enhancement that eliminates the need for custom deserialization, automates schema validation and filtering, and optimizes costs through efficient event handling. Integration with AWS Glue and Confluent registries simplifies development, allowing cleaner data consumption and enhanced scalability.

By Steef-Jan Wiggers

Article: Building Strategic Influence as a Staff Engineer or Engineering Manager

To increase your impact and grow your career, you need to be involved in conversations that happen at a greater scope than the scope you have in your current role. Being involved will give you influence over this, help you direct and maximise your impact, and also allow you to bring better context to your day job, and to those working around you.

By Mark Allen

Podcast: From Code to Strategy: Drive Organizational Impact Through Strategic Conversations and User Focus

In this podcast, Shane Hastie, Lead Editor for Culture & Methods, spoke to Mark Allen about how engineers can expand their influence through strategic conversations, user-focused development practices, and excellence in incident management. Mark emphasizes the importance of building cross-organizational relationships and working on meaningful problems with positive impact.

By Mark Allen

© 2025   Created by Michael Levin.   Powered by

Badges  |  Report an Issue  |  Terms of Service