EMZETT.
Login

Lazy Evaluation (verzögerte Auswertung)

Kurz: Bei Lazy Evaluation wird ein Ausdruck erst ausgewertet, wenn sein Ergebnis wirklich gebraucht wird – und dann höchstens einmal. Das Gegenteil ist die sofortige (eager) Auswertung.

Genauer: Dadurch lassen sich unendliche Folgen beschreiben und teure Berechnungen vermeiden, die nie benötigt werden. Haskell ist durchgehend lazy; in anderen Sprachen gibt es Generatoren, Streams, lazy-Variablen und Kurzschluss-Operatoren.

Im Detail

def zahlen():                      # Generator: liefert Werte bei Bedarf
    n = 1
    while True:
        yield n
        n += 1
 
from itertools import islice
quadrate = (x * x for x in zahlen() if x % 2 == 1)   # Generatorausdruck, nichts berechnet
print(list(islice(quadrate, 5)))                      # [1, 9, 25, 49, 81]
naturalZahlen = [1 ..]                     -- unendliche Liste
print (take 5 (filter even naturalZahlen)) -- [2,4,6,8,10]
val teuer by lazy { println("berechne"); 42 }   // erst beim ersten Zugriff
function* fib() { let [a, b] = [0, 1]; while (true) { yield a; [a, b] = [b, a + b]; } }
const erste = [];
for (const f of fib()) { if (f > 50) break; erste.push(f); }
console.log(erste);

Kurzschluss-Auswertung

a && b und a || b werten b nur aus, wenn nötig: if (x != null && x.laenge > 3) ist deshalb sicher.

Vor- und Nachteile

VorteileNachteile
unendliche Datenstrukturenschwer vorhersagbarer Speicherbedarf (angesammelte Thunks)
Arbeit nur bei BedarfDebugging und Ausführungsreihenfolge sind weniger offensichtlich
elegante PipelinesNebenwirkungen erscheinen zu unerwarteten Zeitpunkten

Lazy Evaluation passt am besten zu reinen Funktionen. Verwandt sind Iteratoren, die Elemente einzeln liefern.

Siehe auch: Iterator, Pure Function, Memoization, Higher-Order-Funktion