"Lazy evaluation"


[Inhalt]...["Strictness" in Haskell]...[Literaturverzeichnis]


5. Vor-/Nachteile


5.1 "Handling"

In einer nicht-strikten, funktionalen Sprache ist die Reihenfolge der Auswertung von Ausdrücken nicht relevant. Somit muss sich auch der Entwickler/Programmierer hierüber keine Gedanken machen. Des weiteren kann er sich darauf verlassen, dass alle (im Zweifel rechenintensiven) Operationen nur dann berechnet werden, wenn ihr Ergebnis für die Weiterverarbeitung benötigt wird. Dadurch wird in vielen Fällen ein problemnaher Entwurf begünstigt, der strukturelle Aspekte der Implementation kaum berücksichtigen muss.
Es besteht beispielsweise die Möglichkeit, Verarbeitungs- oder Kontrollroutinen für Datenstrukturen zu implementieren, die eventuell nicht terminieren. Aufgrund von Parametern oder Ausprägungen der Daten kann die Auswertung dann gesteuert werden.

5.2 Komplexität

Die Komplexität eines Algorithmus oder einer Funktion bezeichnet die Wachstumsrate von Resourcen wie zum Beispiel der Laufzeit gegenüber der Menge der zu verabeitenden Daten. Im Falle von "Lazy evaluation" wird immer die geringste Anzahl an benötigten Werten von Ausdrücken berechnet. Daraus lässt sich schließen, dass in speziellen Problemfällen die Komplexität von Algorithmen in einer nicht strikten Sprache reduziert werden kann. Als Fallbeispiel soll an dieser Stelle der einfache "Insertion-Sort"-Algorithmus zum Sortieren von Feldern dienen.

Code-Beispiel in Haskell [Quelldatei]

>> insert :: Integer->[Integer]->[Integer]
>> insert a [] = [a]
>> insert a (x:xs) | a<x = [a]++(x:xs)
>>     | otherwise = [x]++(insert a xs)

>> sort :: [Integer]->[Integer]
>> sort [] = []
>> sort (x:xs) = (insert x (sort xs))

An zwei Stellen spart die nicht-strikte Auswertung in Einzelfällen Laufzeit ein, weil die Anzahl der auszuwertenden Teilausdrücke reduziert wird. In Kapitel 2 "Nicht-strikte Auswertung" wurde darauf hingewiesen, dass alle namentlichen Vorkommen eines ausgewerteten Ausdrucks durch seinen Wert ersetzt werden. Damit reduziert sich bei doppelten Elementen oder wiederholten Vergleichstests im zu sortierenden Feld die Menge der auszuwertenden Ausdrücke. Das gleiche gilt für den rekursiven Aufruf der "insert"-Methode. Wiederholte Einfügeoperationen werden nur einmal ausgewertet.

Während also die Komplexität des "Insertion-Sort"-Algorithmus in imperativen oder objektorientierten Programmiersprachen als quadratisch zur Anzahl der sortierenden Elemente bekannt ist, hängt sie bei einer nicht-strikten, funktionalen Sprache wie "Haskell" vor allem auch von der Ausprägung des Feldes ab.

5.3 Speicherbedarf

Durch Reduktion der Auswertungen werden Operationen gespart, und damit Laufzeit und Speicher. Zwei Aspekte müssen bei der Programmierung mit nicht-strikter Auswertung jedoch bedacht werden, so dass sich dieser Vorteil nicht umkehrt.

Der erste stellt einen Fall dar, der auch in der "Haskell Mailing List" mehrfach Thema war. Beim Einlesen von Dateien generieren Parser häufig Hilfsstrukturen, in denen die Inhalte der Dateien gepackt werden. Aus diesen Strukturen werden schließlich die relevanten Daten extrahiert. Wenn in diesem Fall die von einem Parser erzeugten Strukturen nicht strikt ausgewertet werden, kann beim Einlesen vieler großer Strukturen der Speicherbedarf erheblich ansteigen.

Der zweite Aspekt besteht darin, dass für die Verwaltung nicht strikter Ausdrücke zusätzlicher Speicher benötigt wird, um die Zuordnung von namentlichen Definitionen zu Ausdrücken zu realisieren, und eine Veranschlagung der auszuwertenden und nicht auszuwertenden Teilausdrücke vorzunehmen, sowie Informationen.


[Inhalt]...["Strictness" in Haskell]...[Literaturverzeichnis]