Yesterday, I got my feet wet creating a simple functional chain to calculate the sum of natural numbers that are multiples of 3 or 5 (thanks Jeff):
var result = (1 .. limit - 1) .asSequence() .filter { item -> item.divisibleBy(3) || item.divisibleBy(5) } .sum()
As you can see, Kotlin looks a lot like Swift. And, like any programming language, you can collect a routine into a function (fun
rather than func
in Kotlin, which makes Kotlin seem like a very “happy fun™” language) for re-use.
Instead of using a temporary result
variable (var
, just like in Swift, although let
is val
) and re-assigning it at each calculation, it’s more elegant to create a reusable component to call for each limit.
The simplest way is to build a function that mimics Swift. You declare fun
, the function name, parameters, the return type (with a :
token), and use the return
keyword to establish the return value:
fun Int.divisibleBy(factor: Int) = this % factor == 0 fun euler1 (limit: Int) : Int { return (1 .. limit - 1) .asSequence() .filter { item -> item.divisibleBy(3) ||item.divisibleBy(5) } .sum() } println("The sum of these multiples is ${euler1(10)}") println("The sum of these multiples is ${euler1(1000)}")
I also munged the calls directly into the print string using ${}
. This is basically the same as using \()
in Swift. The new euler1
function is now almost indistinguishable from Swift.
Kotlin offers a bit more flexibility in its function declarations. You can skip the braces and use assignment to the compound expression, creating an inferred scope for short expressions:
fun euler1 (limit: Int) : Int = (1 .. limit - 1) .asSequence() .filter { item -> item.divisibleBy(3) ||item.divisibleBy(5) } .sum()
Same results, much streamlined declaration.
Like Swift, you can introduce defaulted arguments into your parameter list. This example can be called with zero or one arguments, allowing the printed phrase
to default to “Hello World”.
fun greet(phrase: String = "Hello World") = println(phrase) greet() // "Hello World" greet("Hello Sailor") // "Hello Sailor"
You can also create functional closures/lambda expressions and assign them to variables, as you do in Swift. And, as in Swift, that closure can then be treated like a normal function:
var add : (Int, Int) -> Int = {item, increase -> item + increase } println(add) // Function2<java.lang.Integer, java.lang.Integer, java.lang.Integer> println(add(2, 3)) // 5
Finally, like Swift, you can create infix functionality, such as exponentiation. The first two examples use the infix form, the second two use a standard function call:
infix fun Int.exp(exponent: Int): Int { return (1 .. exponent) .asSequence().map { this } .fold(1) {current, base -> current * base } } println(5 exp 3) // 125 println(2 exp 8) // 256 println(5.exp(3)) // 125 println(2.exp(8)) // 256