Kotlin is a statically typed language that runs on JVM that may compile to JavaScript source code or use the LLVM compiler infrastructure. Since then, it’s grown exponentially in popularity. In 2017, Google officially backed Kotlin as the official language for Android.
And that's just the beginning! Join us here at Kotlin Town and be a part of the evolution of this exciting new language.
Hi folks! Welcome to Kotlin Thursdays. Last week, we examined classes, types, generic functions & parameters as well as covariance & contravariance in Kotlin. Folks told me there weren’t enough sloth facts, and as such, I will do my best to rectify this!
Let’s continue with our sloth and panda crews and write more functions with Kotlin Generics.
Because Kotlin happens to be a functional language, Kotlin has a lot of really powerful characteristics functional purists might consider as pillars for functional programming.
One of these pillars, we’re only going to concern ourselves with the first Kotlin has first class citizens, which means that Kotlin may take functions as parameters. These are known ashigher-order functions. What does it mean for a function to be a first-class citizen? All this means is that you are able topass in a function argument as a parameter in a function.How meta!
This is a feature that is also comparable to Ruby, which facilitates higher order functions. The most common usage of higher order functions involves passing a block to a method, which is an extremely popular Ruby method.
Ruby allows you to inject different blocks into functions usingyield, which involves passing a block to a method. With yield, the block is no longer a parameter to the method. The block isimplicitlypassed to the method. Yield makes executing the block feel like a method invocation within the method invocation rather than using an explicit call.
Kotlin shares a similar idea here, where you can inject different blocks, or functions, into a function.Like Ruby, Kotlin treats functions asfirst-class citizens.In Kotlin, the equivalent of block code is known as lambda functions, indicated by the pattern:
In(A, B) → C,this pattern indicates that a function expects a function parameter that takes 2 parameters typeAand typeB, and returns an output of typeC.
InA.(B) → C,this pattern indicates that a function expects a function parameter that is an extension function of typeAand that extension function takes a single parameterBthat returns an output of typeC.
In the scientific community, 6 species of sloths recognized.
In Costa Rica, there are only 2 types of sloths; the brown-throated three-toedslothand Hoffmann’s two-toedsloth. Black eye patches and “smiling” mouths distinguishCosta Rica’sdocile three-toedsloths, while the larger two-toed variety have white-ringed faces, brown snouts and shaggy coat1.
They actually have quite a bit in common with each other with subtle differences: for example, they both relieve themselves once a week and ARE ABLE TO EXPEL AS MUCH AS 1/3 OF THEIR BODY WEIGHT AT A TIME.
Despite their slow nature and digestive system, they can also swim in a manner that is very similar to the breaststroke.
It turns out, Pandas can also swim! As such, let’s write functions for these particular things that sloths can do:
If we test this out, we’re given:
JERRY CAN SWIM
JERRY FINALLY WENT THIS WEEK
Old weight: 15 | New weight: 13
BAE CAN SWIM
BAE FINALLY WENT THIS WEEK
Old weight: 12 | New weight: 10
ALEX CAN SWIM
ALEX FINALLY WENT THIS WEEK
Old weight: 20 | New weight: 16
We’ve written a higher order function that takes anactionfunction which takes no parameters and gives no outputs, which is of the typeUnit.
Let’s look at another example: All mammals (including giraffes) have 7 cervical vertebrae except for manatees who have 6 and sloths, who have 10. They put yogis to shame with their incredible flexibility!
Let’s write some functions comparing these animals by adding a manatee class and switching ourMammalclass fromopentosealed. Sealed classes are pretty cool, and you can learn more about it from Patrick Cousins’ KotlinConf talk from last year.
This way, we can write when statements in Kotlin, which will only consider these classes under the sealed class as all the exhaustive existing types.
KFunction1 happens to be a covariant/contravariance generic that represents a function with introspection capabilities! You can reference these functions with a ::, which in Kotlin is about meta-programming, including method references, property references and class literals. Sometimes you will see :: without a class in the front, indicating that a method is being call from within the class you’re in, but otherwise, the class you’re referencing a method from sits on the left. Kotlin is smart enough to detect parameters as needed — but you might want toread into it a little moreand experiment yourself!
ClassKFunction1has generic parameters defined as<in P1, out R>,P1withinmodifier andRwithoutmodifier. This means that there will be:
Contravariance onP1introduced byinmodifier — AnyKFunction1<PSuper, R>will be a subtype ofKFunction1<P, R>ifPSuperis a supertype ofP.
Covariance onRintroduced byoutmodifier — AnyKFunction1<P, RSub>will be a subtype ofKFunction1<P, R>ifRSubis a subtype ofR.
Therefore you will be able to assignKFunction1<PSuper, RSub>to a variable of typeKFunction1<P, R>.
You’ll notice that we can feed invertebraeCount()andknownSpeciesCount(), but what if we tried to feed in an endangered function namedisEndangered()?
fun Mammal.isEndangered(): Boolean { return when (this) { is Pandas -> true
is Manatee -> false // upgraded to "threatened"
is Sloths -> true
}
}
If we tried to feed this function in to ourcheckMammalFactsfunction, the compiler would complain, because it expected thetype KFunction1<Mammal, Int>and we’re feeding inKFunction1<Mammal, Boolean>.
Well, I hope you enjoyed these sloth facts and learned a little bit about higher-order functions in Kotlin!
Next week, FOR SURE, we’ll go over reified generics in Kotlin. Till next time!
Kotlin Town
6 members
Description
Interested in Kotlin? Are you a practitioner?
Kotlin is a statically typed language that runs on JVM that may compile to JavaScript source code or use the LLVM compiler infrastructure. Since then, it’s grown exponentially in popularity. In 2017, Google officially backed Kotlin as the official language for Android.
And that's just the beginning! Join us here at Kotlin Town and be a part of the evolution of this exciting new language.
Kotlin Thursdays - Introduction to Kotlin Generics, Part 2
by Amanda Hinchman-Dominguez
Apr 9, 2019
Hi folks! Welcome to Kotlin Thursdays. Last week, we examined classes, types, generic functions & parameters as well as covariance & contravariance in Kotlin. Folks told me there weren’t enough sloth facts, and as such, I will do my best to rectify this!
Let’s continue with our sloth and panda crews and write more functions with Kotlin Generics.
Resources
Higher-Order Functions
Because Kotlin happens to be a functional language, Kotlin has a lot of really powerful characteristics functional purists might consider as pillars for functional programming.
One of these pillars, we’re only going to concern ourselves with the first Kotlin has first class citizens, which means that Kotlin may take functions as parameters. These are known as higher-order functions. What does it mean for a function to be a first-class citizen? All this means is that you are able to pass in a function argument as a parameter in a function. How meta!
This is a feature that is also comparable to Ruby, which facilitates higher order functions. The most common usage of higher order functions involves passing a block to a method, which is an extremely popular Ruby method.
Ruby allows you to inject different blocks into functions using yield, which involves passing a block to a method. With yield, the block is no longer a parameter to the method. The block is implicitly passed to the method. Yield makes executing the block feel like a method invocation within the method invocation rather than using an explicit call.
Kotlin shares a similar idea here, where you can inject different blocks, or functions, into a function. Like Ruby, Kotlin treats functions as first-class citizens. In Kotlin, the equivalent of block code is known as lambda functions, indicated by the pattern:
In (A, B) → C, this pattern indicates that a function expects a function parameter that takes 2 parameters type A and type B, and returns an output of type C.
In A.(B) → C, this pattern indicates that a function expects a function parameter that is an extension function of type A and that extension function takes a single parameter B that returns an output of type C.
In the scientific community, 6 species of sloths recognized.
In Costa Rica, there are only 2 types of sloths; the brown-throated three-toed sloth and Hoffmann’s two-toed sloth. Black eye patches and “smiling” mouths distinguish Costa Rica’s docile three-toed sloths, while the larger two-toed variety have white-ringed faces, brown snouts and shaggy coat1.
Hoffman’s two-toed sloth by minkewink from Pixabay
They actually have quite a bit in common with each other with subtle differences: for example, they both relieve themselves once a week and ARE ABLE TO EXPEL AS MUCH AS 1/3 OF THEIR BODY WEIGHT AT A TIME.
Despite their slow nature and digestive system, they can also swim in a manner that is very similar to the breaststroke.
It turns out, Pandas can also swim! As such, let’s write functions for these particular things that sloths can do:
If we test this out, we’re given:
We’ve written a higher order function that takes an
action
function which takes no parameters and gives no outputs, which is of the typeUnit
.Let’s look at another example: All mammals (including giraffes) have 7 cervical vertebrae except for manatees who have 6 and sloths, who have 10. They put yogis to shame with their incredible flexibility!
Image from Michael Mosimann from Pixabay
Let’s write some functions comparing these animals by adding a manatee class and switching our
Mammal
class fromopen
tosealed
. Sealed classes are pretty cool, and you can learn more about it from Patrick Cousins’ KotlinConf talk from last year.This way, we can write when statements in Kotlin, which will only consider these classes under the sealed class as all the exhaustive existing types.
KFunction1 happens to be a covariant/contravariance generic that represents a function with introspection capabilities! You can reference these functions with a
::
, which in Kotlin is about meta-programming, including method references, property references and class literals. Sometimes you will see :: without a class in the front, indicating that a method is being call from within the class you’re in, but otherwise, the class you’re referencing a method from sits on the left. Kotlin is smart enough to detect parameters as needed — but you might want to read into it a little more and experiment yourself!Class
KFunction1
has generic parameters defined as<in P1, out R>
,P1
within
modifier andR
without
modifier. This means that there will be:P1
introduced byin
modifier — AnyKFunction1<PSuper, R>
will be a subtype ofKFunction1<P, R>
ifPSuper
is a supertype ofP
.R
introduced byout
modifier — AnyKFunction1<P, RSub>
will be a subtype ofKFunction1<P, R>
ifRSub
is a subtype ofR
.Therefore you will be able to assign
KFunction1<PSuper, RSub>
to a variable of typeKFunction1<P, R>
.You’ll notice that we can feed in
vertebraeCount()
andknownSpeciesCount()
, but what if we tried to feed in an endangered function namedisEndangered()
?If we tried to feed this function in to our
checkMammalFacts
function, the compiler would complain, because it expected thetype KFunction1<Mammal, Int>
and we’re feeding inKFunction1<Mammal, Boolean>
.Well, I hope you enjoyed these sloth facts and learned a little bit about higher-order functions in Kotlin!
Next week, FOR SURE, we’ll go over reified generics in Kotlin. Till next time!
Sources Cited
“Sloths.” Costa Rica, www.costarica.com/wildlife/sloths.