Imagine you’re writing universal domain logic for your program. All I/O is provided via an interface (like UI, persistent storage, networking, etc.), you don’t have to think about it, and you almost don’t care about the platform, on which you run. Your program is fairly simple, only a few straightforward tasks. This chapter describes all essentials you need to write it. The foundational basics that you can build upon: data, processing primitives, and functions to reuse code.

Functions

Functions are an elegant way to reuse parts of your program. They help to split tasks into smaller tasks and allow zooming between levels of abstraction. For example, you don’t have to write code for efficient sorting every time you need to sort your collection. You can reuse an already written routine. Functions define a clear scope, inputs and outputs. Without them, programs would be very long and tedious.

You can even think of your whole program as functions composing into each other, according to an ingenious paradigm called functional programming.

Functions

A typical function with inputs and outputs. It can be called in many different ways; default arguments, named parameters, and trailing lambdas supported:

fun doSomething(
  times: Int, notifyAfterEachStep: Boolean = true, something: () -> Unit
): List<String> {
  val result = mutableListOf<String>()

  for (i in 1..times) {
    something()
    if (notifyAfterEachStep) {
      result.add("Step $i finished")
    }
  }

  result.add("Done")
  return result
}

doSomething(3, false, {})
doSomething(3) {}
doSomething(something = {}, times = 3)
doSomething(3, something = {})

A function without inputs or outputs that does something cryptic inside. Technically, it’s not a function, but a procedure.

fun sideEffect() {}

A function can be referenced for later use:

doSomething(1, something = ::sideEffect)

A function that is implemented by a single expression:

fun toString(x: Any) = "$x"

Functions can nest:

fun histogram(text: String): Map<Char, Int> {
  val result = mutableMapOf<Char, Int>()
  fun recordLetter(char: Char) {
    val count = result.getOrDefault(char, 0)
    result[char] = count + 1
  }

  for (c in text) recordLetter(c)
  return result
}

[--]