EMZETT.
Login

Kurz: let ic = open_in datei in (try while true do let zeile = input_line ic in Printf.printf ”> %s\n” zeile done with End_of_file -> close_in ic);

Teil des Kurses OCaml

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

Dateien lesen und schreiben

let () =
  let datei = Filename.temp_file "ocaml" ".txt" in
  let oc = open_out datei in
  output_string oc "eins\nzwei\ndrei\n";
  Printf.fprintf oc "Zahl: %d\n" 42;
  close_out oc;
 
  let ic = open_in datei in
  (try
     while true do
       let zeile = input_line ic in
       Printf.printf "> %s\n" zeile
     done
   with End_of_file -> close_in ic);
 
  (* mit Hilfsfunktion, die die Datei zuverlässig schließt *)
  let alle_zeilen pfad =
    let ic = open_in pfad in
    Fun.protect ~finally:(fun () -> close_in ic) (fun () ->
      let rec lies acc = match input_line ic with
        | z -> lies (z :: acc)
        | exception End_of_file -> List.rev acc in
      lies [])
  in
  Printf.printf "%d Zeilen\n" (List.length (alle_zeilen datei));
  Sys.remove datei;
  Printf.printf "%b\n" (Sys.file_exists datei)

Ausgabe:

> eins
> zwei
> drei
> Zahl: 42
4 Zeilen
false

Kommandozeile und Umgebung

let () =
  Printf.printf "Argumente: %d\n" (Array.length Sys.argv - 1);
  (match Sys.getenv_opt "NICHT_GESETZT_XYZ" with
   | Some v -> print_endline v
   | None -> print_endline "Variable fehlt");
  Printf.printf "%b\n" (Sys.os_type = "Unix");
  Printf.printf "%d\n" Sys.word_size

Ausgabe:

Argumente: 0
Variable fehlt
true
64

Formatierte Ausgabe mit Format

type person = { name : string; alter : int }
 
let pp_person fmt p = Format.fprintf fmt "{ name = %s; alter = %d }" p.name p.alter
 
let () =
  Format.printf "%a@." pp_person { name = "Mia"; alter = 17 };
  Format.printf "@[<v>Zeile 1@,Zeile 2@]@.";
  let s = Format.asprintf "%d-%s" 7 "x" in
  print_endline s;
  Printf.printf "%s\n" (Printf.sprintf "%08.3f" 3.14159)

Ausgabe:

{ name = Mia; alter = 17 }
Zeile 1
Zeile 2
7-x
0003.142

Dune und Pakete

Echte Projekte nutzen dune:

(* dune-project *)
(lang dune 3.0)
 
(* bin/dune *)
(executable (name main) (libraries str))
 
(* bin/main.ml *)
let () = print_endline "Hallo aus dune"
opam switch create 5.2.0      # Compiler installieren
opam install dune utop ocaml-lsp-server ocamlformat
dune build                    # bauen
dune exec ./bin/main.exe      # starten
dune test                     # Tests ausführen
dune fmt                      # mit ocamlformat formatieren
BibliothekZweck
Base/Core (Jane Street)Alternative Standardbibliothek
Lwt, Async, EioNebenläufigkeit und asynchrone I/O
Alcotest, OUnitTests
CmdlinerKommandozeilen-Parser
YojsonJSON
Menhir, ocamllexParser-Generatoren
DreamWebframework

Tipp

Das Buch „Real World OCaml“ und ocaml.org/docs sind die besten kostenlosen Quellen.

Tests schreiben

let assert_gleich name erwartet erhalten =
  if erwartet = erhalten then Printf.printf "ok   %s\n" name
  else Printf.printf "FAIL %s\n" name
 
let rec fak n = if n <= 1 then 1 else n * fak (n - 1)
 
let () =
  assert_gleich "fak 5" 120 (fak 5);
  assert_gleich "fak 0" 1 (fak 0);
  assert_gleich "liste" [2; 4] (List.map (fun x -> x * 2) [1; 2]);
  assert (fak 3 = 6);
  print_endline "alle Tests laufen"

Ausgabe:

ok   fak 5
ok   fak 0
ok   liste
alle Tests laufen

Merke

  • Dateien: open_in/open_out, input_line, Fun.protect zum sicheren Schließen
  • Format für hübsche Ausgabe, Printf.sprintf für formatierte Strings
  • Projekte baut man mit dune und installiert Pakete mit opam
  • Tests: Alcotest oder OUnit; assert für schnelle Prüfungen

Übungsaufgabe

Lies eine Textdatei und gib die Zeilenanzahl und die längste Zeile aus.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Funktional vertieft: Lazy, GADTs und Objekte

Weiter: Referenz und Spickzettel

Alle Kapitel: OCaml im Überblick