EMZETT.
Login

Kurz: Funktionen sind Werte. Argumente werden ohne Klammern und Kommas übergeben; jede Funktion hat genau einen Parameter, mehrere werden curryt:

Teil des Kurses OCaml

Kapitel 2 von 8 im Kurs OCaml. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

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
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 status

Ausgabe:

5: 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)

Ausgabe:

3628800
102334155
6

Tipp

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" !summe

Ausgabe:

1 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 b

Ausgabe:

null
zwei
negativ
viele
true false
1 x

Merke

  • Funktionen: let f x y = ...; mehrere Argumente werden curryt, partielle Anwendung ist normal
  • if ist ein Ausdruck; Schleifen sind meist Rekursion (let rec)
  • for, while, ref (!, :=) für imperativen Stil
  • match ... with und function für Pattern Matching

Übungsaufgabe

Schreibe eine endrekursive Funktion potenz basis exponent für ganze Zahlen.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Einführung und erstes Programm

Weiter: Listen, Tupel und Records

Alle Kapitel: OCaml im Überblick