Kiste
EN

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 run und kiste 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.