Funktionen
Funktionen sind Werte. Argumente werden ohne Klammern und Kommas übergeben; jede Funktion hat genau einen Parameter, mehrere werden curryt:
let quadrat x = x * x
let addiere a b = a + b
let begruesse name = "Hallo, " ^ name ^ "!"
let () =
Printf.printf "%d %d\n" (quadrat 7) (addiere 3 4);
print_endline (begruesse "Mia");
(* partielle Anwendung *)
let plus10 = addiere 10 in
Printf.printf "%d\n" (plus10 5);
(* anonyme Funktionen *)
let verdopple = fun x -> x * 2 in
Printf.printf "%d\n" (verdopple 21);
(* Funktionen als Argumente *)
let wende_zweimal f x = f (f x) in
Printf.printf "%d\n" (wende_zweimal (fun n -> n + 3) 10)49 7 Hallo, Mia! 15 42 16
if, Vergleich und Ausdrücke
if ist ein Ausdruck und liefert einen Wert. Beide Zweige haben denselben Typ:
let vorzeichen n = if n > 0 then "positiv" else if n < 0 then "negativ" else "null"
let maximum a b = if a > b then a else b
let () =
List.iter (fun n -> Printf.printf "%d: %s\n" n (vorzeichen n)) [5; -2; 0];
Printf.printf "%d\n" (maximum 3 9);
let alter = 20 in
let status = if alter >= 18 then "volljährig" else "minderjährig" in
print_endline status5: positiv -2: negativ 0: null 9 volljährig
Rekursion
Schleifen ersetzt OCaml meist durch Rekursion. Mit let rec darf sich eine Funktion selbst aufrufen:
let rec fakultaet n = if n <= 1 then 1 else n * fakultaet (n - 1)
(* endrekursiv: Akkumulator, kein wachsender Stack *)
let fib n =
let rec schritt a b i = if i = 0 then a else schritt b (a + b) (i - 1) in
schritt 0 1 n
let rec ggt a b = if b = 0 then a else ggt b (a mod b)
let () =
Printf.printf "%d\n" (fakultaet 10);
Printf.printf "%d\n" (fib 40);
Printf.printf "%d\n" (ggt 48 18)3628800 102334155 6
Schleifen und Veränderlichkeit
OCaml hat auch imperative Schleifen und veränderliche Referenzen:
let () =
for i = 1 to 5 do Printf.printf "%d " i done;
print_newline ();
for i = 5 downto 1 do Printf.printf "%d " i done;
print_newline ();
let zaehler = ref 0 in
while !zaehler < 3 do
Printf.printf "Durchlauf %d\n" !zaehler;
incr zaehler
done;
let summe = ref 0 in
for i = 1 to 100 do summe := !summe + i done;
Printf.printf "%d\n" !summe1 2 3 4 5 5 4 3 2 1 Durchlauf 0 Durchlauf 1 Durchlauf 2 5050
ref 0 erzeugt eine veränderliche Zelle, !r liest, r := wert schreibt.
Pattern Matching
match zerlegt Werte nach Form und ist in OCaml allgegenwärtig:
let zahlwort = function
| 0 -> "null"
| 1 -> "eins"
| 2 -> "zwei"
| n when n < 0 -> "negativ"
| _ -> "viele"
let ist_vokal c = match c with
| 'a' | 'e' | 'i' | 'o' | 'u' -> true
| _ -> false
let () =
List.iter (fun n -> print_endline (zahlwort n)) [0; 2; -5; 99];
Printf.printf "%b %b\n" (ist_vokal 'e') (ist_vokal 'x');
let (a, b) = (1, "x") in
Printf.printf "%d %s\n" a bnull zwei negativ viele true false 1 x
Merke
- Funktionen:
let f x y = ...; mehrere Argumente werden curryt, partielle Anwendung ist normal ifist ein Ausdruck; Schleifen sind meist Rekursion (let rec)for,while,ref(!,:=) für imperativen Stilmatch ... withundfunctionfür Pattern Matching
Aufgabe
Schreibe eine endrekursive Funktion potenz basis exponent für ganze Zahlen.