Semantik (Wirkung, Verständnis vom Programm) durch sich in der Zeit ändernden Zustand (Stand der Bearbeitung, Variablenbelegung) gegeben - und das ist zu schwer für das menschliche Hirn!
Beispiel: Partitionierung in Quicksort:
i:=links; j:=rechts-1;
loop
while a(i)<trenn loop i:=i+1; end loop;
while a(j)>trenn loop j:=j-1; end loop;
if i>=j then exit; end if;
temp:=a(i); a(i):=a(j); a(j):=temp;
i:=i+1; j:=j-1;
end loop;
?? Was gilt hier ??
?? Kommt man überhaupt dahin ??
imperative Programmierung ist mühsam, logisch anspruchsvoll und fehleranfällig, denn:
i: integer := 1;
a: array(1..10) of integer := (others=>0);
function f return integer is - Seiteneffekt
begin i:=i+1; return i; end f;
dann z.B.:
i:=i+f;
a(i):=f;
a(f):=a(f);
a(i+f):=i+f;
if 2*(i+f)=(i+f)+(i+f) then ...
...
Klar: Ziel nicht, Reihenfolge der Auswertung in Gebilden wie ``a(f):=a(f)'' zu normieren, sondern das Problem zu vermeiden!
"`higher order functions"'
vgl. "`map"', "`fold"' in Programmieren II
vgl. Mathematik:
Differentiation als Transformation von reellen Funktionen, also:
diff :: (Float->Float) -> (Float->Float)
diff(sin) = cos
ist in funktionaler Programmierung numerisch ohne weiteres machbar!
effiziente Kombination vom Programmteilen, die
ohne Rücksicht auf spezifische (beschränkte) Anwendung entworfen sind.
Beispiel: | Test ob Zahl n prim ist |
Annahme: |
es gebe Funktion |
divisors :: Int -> [Int] | |
die Liste aller Teiler einer gegebenen Zahl liefert | |
dann: |
is_prim n = divisors n == [1,n] |
wobei: |
falls n keine Primzahl ist wird divisiors nur |
solange ausgewertet, bis erstes Gegenbeispiel | |
gefunden wurde. | |
also: | Abbruchbedingung für divisors implizit, |
also divisors für ganz verschiedene Zwecke | |
nutzbar (vgl.: wie macht man das in imperativer Programmierung ?? ) |
Ferner: lazy evaluation erlaubt Arbeit mit (potentiell) unendlichen Datenstrukturen (Listen, Bäumen, ...).