Skip to main content

Understanding lambda in Kotlin

Kotlin is very concise language. You can achieve same functionality with fewer characters compared to Java. But as an experienced developer, it was easy for me to switch from Java to Kotlin. Same might not be true for those who are new to programming. I had tough time explaining how Lambda works to a trainee who was new to programming.
For instance, I was trying to explain a simple map function that maps objects of one type to another. I have two simple classes
class Journal(id: String)
class DisplayJournal(journal: Journal)
view raw journalclass hosted with ❤ by GitHub
and a simple usage of map function
val listOfDisplayJournals = listOf(Journal("123")).map { DisplayJournal(it) }
view raw map hosted with ❤ by GitHub
I came up with following step by step code to explain what's actually going on. All the code snippets do the exact same thing. Converting imperative to functional code at the end.
Extract the list of journals to new variable.
val listOfJournals = listOf(Journal("123"))
val listOfDisplayJournals = listOfJournals.map { DisplayJournal(it) }
view raw extractlist hosted with ❤ by GitHub
The map function is being executed here, we can specify the round brackets to be explicit
val listOfJournals = listOf(Journal("123"))
val listOfDisplayJournals = listOfJournals.map() { DisplayJournal(it) }
view raw roundbrac hosted with ❤ by GitHub
The code after map function including the curly braces is actually a lambda. It is the last (and only) parameter for the map function. So we move it inside the round brackets.
val listOfJournals = listOf(Journal("123"))
val listOfDisplayJournals = listOfJournals.map ({ DisplayJournal(it) })
view raw insidebrackets hosted with ❤ by GitHub
The variable it is default name of the parameter in the lambda, if the lambda takes exactly one parameter. We can specify the name explicitly in the definition
val listOfJournals = listOf(Journal("123"))
val listOfDisplayJournals = listOfJournals.map ({it-> DisplayJournal(it) })
view raw itparam hosted with ❤ by GitHub
The type of the parameter was implicit. As map function is being called on list of Journal, the lambda parameter type is Journal. Below we specify the type for it.
val listOfJournals = listOf(Journal("123"))
val listOfDisplayJournals = listOfJournals.map ({it: Journal-> DisplayJournal(it) })
view raw ittype hosted with ❤ by GitHub
Let's rename it variable so that it is more readable
val listOfJournals = listOf(Journal("123"))
val listOfDisplayJournals = listOfJournals.map ({journal: Journal-> DisplayJournal(journal) })
view raw renameit hosted with ❤ by GitHub
Now this lambda can be extracted out to a new variable. Below we assign the lambda expression to the new variable and replace the lambda in map function with this new variable
val listOfJournals = listOf(Journal("123"))
val convertJournalToDisplayJournal = { journal: Journal -> DisplayJournal(journal) }
val listOfDisplayJournals = listOfJournals.map (convertJournalToDisplayJournal)
view raw extrlambda hosted with ❤ by GitHub
The new variable type again is implicit above. Let's specify it explicitly. It takes a parameter of type Journal and returns DisplayJournal
val listOfJournals = listOf(Journal("123"))
val convertJournalToDisplayJournal: (Journal)->DisplayJournal = { journal: Journal -> DisplayJournal(journal) }
val listOfDisplayJournals = listOfJournals.map (convertJournalToDisplayJournal)
view raw lambdatype hosted with ❤ by GitHub
As lambda is nothing but a function, let's define it as a function. We add the fun keyword here. Note that Kotlin functions are first-class, which means that I can assign those to a variable.
val listOfJournals = listOf(Journal("123"))
val convertJournalToDisplayJournal: (Journal)->DisplayJournal = fun(journal: Journal) {
DisplayJournal(journal)
}
val listOfDisplayJournals = listOfJournals.map (convertJournalToDisplayJournal)
view raw anonfun hosted with ❤ by GitHub
We can also define this function explicitly and use the function reference using ::. Note that in the function definition we have added return keyword which returns a value from the function body
val listOfJournals = listOf(Journal("123"))
fun convertJournalToDisplayJournalFn(journal: Journal): DisplayJournal{
return DisplayJournal(journal)
}
val convertJournalToDisplayJournal: (Journal)->DisplayJournal = ::convertJournalToDisplayJournalFn
val listOfDisplayJournals = listOfJournals.map (convertJournalToDisplayJournal)
view raw lambdatofun hosted with ❤ by GitHub
We can also convert this function to expression body by removing the curly braces and the return keyword
val listOfJournals = listOf(Journal("123"))
fun convertJournalToDisplayJournalFn(journal: Journal): DisplayJournal = DisplayJournal(journal)
val convertJournalToDisplayJournal: (Journal)->DisplayJournal = ::convertJournalToDisplayJournalFn
val listOfDisplayJournals = listOfJournals.map (convertJournalToDisplayJournal)
view raw exprebody hosted with ❤ by GitHub
The return type that is explicitly defined for the function can be removed in case of expression body
val listOfJournals = listOf(Journal("123"))
fun convertJournalToDisplayJournalFn(journal: Journal) = DisplayJournal(journal)
val convertJournalToDisplayJournal: (Journal)->DisplayJournal = ::convertJournalToDisplayJournalFn
val listOfDisplayJournals = listOfJournals.map (convertJournalToDisplayJournal)
view raw 1 hosted with ❤ by GitHub

Comments

Popular posts from this blog

JMockit : passing the mock variable

We had a really long interface, that needed to be mocked. One class's contructor had this interface object as an argument. With my traditional mocking approach, I would have written a @Mockclass that implements this interface, @Mock only the required method, and leave other methods unimplemented. Create a new instance of this mocked class. But that looked like BIG non required code. @Injectable to rescue JMockit have @Injectable annotation that you pass to test method as a parameter and define the Expectation. And thats it. Here is the code snippet