As you might have guessed, I got very busy between March 2021 & March 2022. In fact I have been very busy at work & play between March 2020 & January 2022. Remote work has its own challenges. But work from office is even more hassle.
The last time I learned Kotlin was in July 2019. 3 years later, I am ready to learn it again with all the new features but for backend software development this time. For me, Kotlin is a combination of 4 languages now - Java, Python, Golang & Swift.
Kotlin is so much fun, because we get to write so many "fun"s & the capability to write extensions on top of them.
One feature I stumbled across and got surprised at is the ability to use data types as variable names as you can see in the example above.
Code:
fun main() {
var MSG = "Hello"
val Int = 5
val String = "World"
val Boolean = false
println(Int)
println(String)
println(!Boolean)
MSG+=','
var greeting = "$MSG world!"
println(greeting)
}
Output:
5
World
true
Hello, world!
Functions are fun
A function with two Int
parameters and Int
return type.
A function body can be an expression. Its return type is inferred.
A function that returns no meaningful value.
Unit
return type can be omitted.
In Kotlin, if
can also be used as an expression.
There is a new thing worth learning now. It is called the "when" expression. Seems pretty similar to "switch" case.
fun sum(a: Int, b: Int): Int = a + b
fun sayHello(): Unit = println("Hello")
fun isPositive(number: Int): Boolean = number > 0
Return type can be inferred and therefore omitted when feasible
fun sum(a: Int, b: Int) = a + b // Int
fun sayHello() = println("Hello") // Unit
fun isPositive(number: Int) = number > 0 // Boolean
If you don't like for, while & do-while, or find it all too confusing, here is a new way to use loops - repeat
fun main() {
repeat(3) {
println("Hello")
}
}
fun main() {
repeat(5) {
println("Kotlin")
}
}
If you don't like writing too much to make code modular, put functions aside, make way for lambda expressions.
fun(a: Int, b: Int): Int {
return a * b
}
{ a: Int, b: Int -> a * b }
To invoke it inline,
println({ a: Int, b: Int -> a * b } (5,3))
We can assign the function to a variable and then invoke it by invoking the variable.
val mul1 = fun(a: Int, b: Int): Int {
return a * b
}
val mul2 = { a: Int, b: Int -> a * b }
println(mul1(2, 3)) // prints "6"
println(mul2(2, 3)) // prints "6" too
Lambda can help save lines of code as well as impact code readability.
fun isNotDot(c: Char): Boolean = c != '.'
val originalText = "I don't know... what to say..."
val textWithoutDots = originalText.filter(::isNotDot)
val originalText = "I don't know... what to say..."
val textWithoutDots = originalText.filter({ c: Char -> c != '.' })
val textWithoutDots = originalText.filter(){ c -> c != '.' }
val textWithoutDots = originalText.filter { c -> c != '.' }
val textWithoutDots = originalText.filter { it != '.' }
fun sum(a: Int, b: Int): Int = a + b
val mul2 = { a: Int, b: Int -> a * b }
Functions can be returned as objects
fun identity(x: Int) = x
fun half(x:Int) = x/2
fun zero(x:Int) = 0
fun generate(functionName: String): (Int) -> Int {
if (functionName == "identity") return ::identity
else if (functionName == "half") return ::half
else return ::zero//if (functionName == "zero")
}
fun composition(value: Int, y: (Int) -> Int, g: (Int) -> Int): Int {
return y(g(value))
}
Double Dots & IN for Ranges
Kotlin allows generating ranges and checking inclusion in ranges using .. & in.
If we need to check that a value is not within a range, we can just add !
(not) before in
.
val within = 10 !in 5..50 // true
val notWithin = 100 !in 10..99 // true
We may combine ranges using standard logical operators.
val within = c in 5..10 || c in 20..30 || c in 40..50
You can assign a range to a variable and use it later.
val range = 100..200
println(300 in range) // false
In addition to integer ranges, we can also use ranges of characters and even strings (according to dictionary order).
println('b' in 'a'..'c') // true
println('k' in 'a'..'e') // false
println("hello" in "he".."hi") // true
println("abc" in "aab".."aac") // false
That's gonna be some fun for permutations & combinations.
When in dots, have fun!
val result = when (op) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
else -> "Unknown operator"
}
println(result)
when (op) {
"+", "plus" -> println(a + b)
"-", "minus", -> println(a - b) // trailing comma
"*", "times" -> println(a * b)
else -> println("Unknown operator")
}
when (op) {
"+", "plus" -> {
val sum = a + b
println(sum)
}
"-", "minus" -> {
val diff = a - b
println(diff)
}
"*", "times" -> {
val product = a * b
println(product)
}
else -> println("Unknown operator")
}
println(when(op) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
else -> "Unknown operator"
})
when (n) {
0 -> println("n is zero")
in 1..10 -> println("n is between 1 and 10 (inclusive)")
in 25..30 -> println("n is between 25 and 30 (inclusive)")
else -> println("n is outside a range")
}
when {
n == 0 -> println("n is zero")
n in 100..200 -> println("n is between 100 and 200")
n > 300 -> println("n is greater than 300")
n < 0 -> println("n is negative")
}
when(readln().toInt()) {
in 0..9 -> println(1)
in 10..99 -> println(2)
in 100..999 -> println(3)
in 1000..9999 -> println(4)
}
fun Request.getBody() =
when (val response = executeRequest()) {
is Success -> response.body
is HttpError -> throw HttpException(response.status)
}
Functions can be passed as parameters to other functions
fun odd(x: Int): Boolean = x % 2 == 1
println(odd(6)) // => false
println(odd(7)) // => true
// If the return type can be inferred then we don't need to specify it.
fun even(x: Int) = x % 2 == 0
println(even(6)) // => true
println(even(7)) // => false
// Functions can take functions as arguments and return functions.
fun not(f: (Int) -> Boolean): (Int) -> Boolean {
return {n -> !f.invoke(n)}
}
// Named functions can be specified as arguments using the :: operator.
val notOdd = not(::odd)
val notEven = not(::even)
// Lambda expressions can be specified as arguments.
val notZero = not {n -> n == 0}
Extension functions
fun String.remove(c: Char): String {
return this.filter {it != c}
}
println("Hello, world!".remove('l')) // => Heo, word!