Kotlin Idioms

Mal ein Thread für Tipps zur Kotlin-Syntax.

Mich hat gestört, dass man die Kurzschreibweise für Funktionen (mit Gleichheitszeichen) nicht verwenden kann, wenn man z.B. vorher noch requirements testet:

fun foo(arg:Int): Int {
   require(arg >= 0) { "muss positiv sein" }
   return Math.sqrt(arg)
}

Mit der Bibliotheks-Funktion let geht es doch:

fun foo(arg:Int) = 
  {require(arg >= 0) { "muss positiv sein" }}.invoke().let {Math.sqrt(arg)}

Insgesamt sollte man sich let, run, apply und invoke etwas näher ansehen.

Noch ein guter Tipp für data class: Wenn man dessen Konstruktor-Parameter noch irgendwie manipulieren oder testen will, hilft ein “Fake-Konstruktor” weiter. Nehmen wie dieses Beispiel, wo die übergebene Liste “eigentlich” vorher sortiert werden soll:

data class Foo(val list:List<String>)

Die Lösung ist etwas umständlich, funktioniert aber einwandfrei:

data class Foo private constructor (val list: List<String>) {
   companion object Companion {
      operator fun invoke(list: List<String>) = Foo(list.sorted())
   }
}

Falls jemand einen hübscheren Weg weiß, möge er ihn preisgeben…

Ich liebe Extension-Methoden, auch weil sich damit Löcher in der API so schön stopfen lassen. Java-Streams haben kein foldLeft? Kein Problem:

fun <T, R> Stream<T>.foldLeft(accu: R, fn: (R, T) -> R): R {
    var result = accu
    forEach { result = fn(result, it) }
    return result
}

Jetzt habe ich an jedem Stream mein foldLeft:

stream.foldLeft(StringBuilder()){ sb, s -> sb.append(s) }