Funktionen
Eine Funktion ist ein Stück Code, das du benennst und immer wieder aufrufen kannst.
8.1 Funktion definieren
funktion grüße() {
sag "Hallo!"
}
grüße() // Ruft die Funktion auf
grüße() // Nochmal
grüße() // Nochmal
8.2 Funktion mit Parametern
funktion grüße(name) {
sag "Hallo " + name
}
grüße("Sascha") // "Hallo Sascha"
grüße("Anna") // "Hallo Anna"
8.3 Funktion mit Rückgabewert
funktion addiere(a, b) {
gib a + b
}
nimm summe = addiere(5, 3)
sag summe // 8
Hinweis: gib beendet die Funktion sofort und gibt den Wert zurück.
8.4 Funktion mit Standardwerten
funktion grüße(name = "Welt") {
sag "Hallo " + name
}
grüße() // "Hallo Welt"
grüße("Sascha") // "Hallo Sascha"
8.5 Funktionen sind Werte
Du kannst eine Funktion in einer Variablen speichern:
nimm verdoppeln = funktion(x) {
gib x * 2
}
sag verdoppeln(5) // 10
Du kannst eine Funktion an eine andere Funktion übergeben:
funktion anwenden(f, wert) {
gib f(wert)
}
funktion quadrieren(x) {
gib x * x
}
sag anwenden(quadrieren, 4) // 16
Das nennt man Funktionen höherer Ordnung — sehr mächtig!
8.6 Rekursion (Funktion ruft sich selbst)
funktion fakultät(n) {
wenn n <= 1 {
gib 1
}
gib n * fakultät(n - 1)
}
sag fakultät(5) // 120
8.7 Funktionen als Werte und Closures
Eine Funktion ist in Kiste ein ganz normaler Wert: du kannst sie einer
Variablen zuweisen, aus einer Funktion zurückgeben und später aufrufen. Eine
Funktion ohne Namen schreibst du mit funktion(...) { ... }:
nimm verdopple = funktion(x) { gib x * 2 }
sag verdopple(21) // 42
Eine Funktion kann auch innerhalb einer anderen stehen oder eine Funktion zurückgeben. Die innere Funktion „erinnert" sich dabei an die Variablen der äußeren — das nennt man eine Closure:
funktion addierer(basis) {
gib funktion(y) { gib basis + y } // fängt `basis`
}
nimm plus10 = addierer(10)
sag plus10(5) // 15
sag plus10(100) // 110
Gefangene Variablen werden per Referenz geteilt — eine Closure kann sie auch verändern und merkt sich den Zustand zwischen den Aufrufen:
funktion mache_zähler() {
nimm n = 0
gib funktion() {
n = n + 1
gib n
}
}
nimm z = mache_zähler()
sag z() // 1
sag z() // 2
sag z() // 3
Jeder Aufruf von mache_zähler() legt einen eigenen Zähler an — zwei
Closures stören sich nicht. Du kannst eine Funktion auch verschachtelt mit
Namen schreiben (funktion innen() { ... } mitten im Körper); sie verhält sich
genau wie eine zugewiesene funktion(...)-Closure.
Hinweis: Closures funktionieren identisch mit
kiste runundkiste build.
Closures an Funktionen höherer Ordnung übergeben
Du kannst ein Funktions-Literal direkt an Listen-Funktionen wie
liste.abgebildet, liste.gefiltert oder liste.gesammelt übergeben — auch
wenn es eine äußere Variable fängt. Vorher brauchtest du dafür einen
Top-Level-Funktions-Namen; jetzt geht es inline:
nutze liste
nimm zahlen = [1, 2, 3, 4, 5, 6]
nimm schwelle = 3
sag liste.gefiltert(zahlen, funktion(x) { gib x > schwelle }) // [4, 5, 6]
nimm faktor = 10
sag liste.gesammelt(zahlen, 0, funktion(akku, x) { gib akku + x * faktor }) // 210
Das gilt auch für GUI-Handler: ein Klick-Handler kann eine lokale Variable fangen, statt den Umweg über eine globale Variable zu nehmen:
nutze gui
funktion baue(fenster) {
nimm basis = 41
nimm k = gui.knopf_neu("Klick")
gui.bei_klick(k, funktion(knopf) { sag "wert={basis + 1}" }) // fängt basis
gui.zeige(fenster, k)
}
Auch das funktioniert in allen drei Backends gleich (kiste run, VM,
kiste build).
Vollständiges Beispiel: beispiele/closures.ki.