Kurz: Funktionen sind Werte. Argumente werden ohne Klammern und Kommas übergeben; jede Funktion hat genau einen Parameter, mehrere werden curryt:
Teil des Kurses OCaml
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)Ausgabe:
49 7
Hallo, Mia!
15
42
16if, 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 statusAusgabe:
5: positiv
-2: negativ
0: null
9
volljährigRekursion
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)Ausgabe:
3628800
102334155
6Tipp
Endrekursive Aufrufe (der Aufruf steht ganz am Ende) werden vom Compiler in eine Schleife umgewandelt und verbrauchen keinen Stack.
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" !summeAusgabe:
1 2 3 4 5
5 4 3 2 1
Durchlauf 0
Durchlauf 1
Durchlauf 2
5050ref 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 bAusgabe:
null
zwei
negativ
viele
true false
1 xMerke
- 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
Übungsaufgabe
Schreibe eine endrekursive Funktion potenz basis exponent für ganze Zahlen.
Quiz zur Selbstkontrolle
Wie definiert man eine rekursive Funktion?
- let rec (richtig)
- let loop
- def rec
- function recursive
Was liefert ein if-Ausdruck?
- Einen Wert (richtig)
- Nur unit
- Nichts
- Einen Fehler
Wie liest man den Wert einer Referenz r?
- !r (richtig)
- r
- *r
- r.value
Weiter im Kurs
Zurück: Einführung und erstes Programm
Weiter: Listen, Tupel und Records
Alle Kapitel: OCaml im Überblick