OCaml (https://www.ocaml.org/) est un langage de programmation fonctionnelle, statiquement typé, qui peut être utilisé en mode interprété (comme Python) ou compilé. Conçus par des chercheurs de l'INRIA, hériter de CAML puis caml_light, le langage utilisé pour l'enseignement de l'option informatique en classes préparatoires MPSI et MP en France.
OCaml, et les langages fonctionnels en général, n'est pas un langage très populaire dans le monde, en comparaison de C/C++, Java, PHP, Python et Javascript (les cinq plus populaires), mais il a des avantages, et reste très utilisé pour l'enseignement de l'informatique théorique en France.
Liens :
- http://caml.inria.fr/ et https://www.ocaml.org/ sont les sites officiels du langage,
- http://try.ocamlpro.com/ pour essayer le langage depuis un navigateur,
- Par exemple http://www.janestreet.com/ est un groupe de trading, qui est connu pour utiliser des applications codées en OCaml,
- Un autre exemple, Facebook utilise OCaml pour ses outils d'analyse statique de code, comme flow et infer, et pour son environnement Reason.
OCaml est connu pour manquer d'environnement de développement moderne et "séduisant", et la plupart des enseigants utilisent Emacs et son mode Tuareg pour Caml/OCaml, qui manque de modernité.
Les élèves habitués à des logiciels très modernes, faciles d'accès et très visuels, se retrouvent confrontés à un logiciel qui n'a guère évolué depuis les années 1980.
Mon expérience montre que mêmes des élèves de niveau master, préparant l'agrégation de mathématiques option informatique à l'ENS de Rennes, ont un peu de mal à prendre correctement en main le logiciel Emacs et son mode Tuareg. A l'opposé, j'ai vu des élèves de première et deuxième années de prépa (MPSI et PSI) maîtriser très bien l'environnement Jupyter, qu'ils avaient appris à utiliser pour l'oral "maths avec Python" du concours CentraleSupélec.
Liens :
Utiliser des notebooks Jupyter avec le kernel ocaml-jupyter
(https://github.com/akabe/ocaml-jupyter) est une très bonne solution pour montrer du code, des commentaires, et les résultats d'évaluation des morceaux de code, pour des cours, TD ou TP d'informatique avec OCaml.
let entier = 0
and flottant = 1.0
and chaine = "Superman"
and fonction = fun x -> fun y -> x + y
;;
Comme pour Python, chaque cellule contient du texte (en Markdown), ou du code, et sa sortie une fois exécuté. Il est très facile d'écrire des sujets de TP ou d'examen, qui mélangent tous ces contenus, grâce à Jupyter.
Les documents écrits avec Jupyter peuvent ensuite être convertis en PDF, en HTML, ou d'autres formats.
Exécuter une cellule donne la signature des objets définis dans la cellule, i.e., leurs valeurs et/ou leurs types.
Par exemple, si on définit fact(n) = n!
avec $n! = 1 \times 2 \times \dots \times n$, fact : int -> int
est la signature de la fonction fact
.
let rec fact = function
| 0 -> 1
| 1 -> 1
| n -> n * (fact (n-1))
;;
for i = 0 to 10 do
Printf.printf "fact(%i) = %i\n" i (fact i);
done;
flush_all();;
Et par exemple pour la fonction calculant les termes positifs de la suite de Fibonacci :
let rec fibo = function
| 0 -> 1
| 1 -> 1
| n -> (fibo (n-1)) + (fibo (n-2))
;;
for i = 10 to 20 do
Printf.printf "fibo(%i) = %i\n" i (fibo i);
done;
flush_all();;
let timeit f x () =
let debut = Sys.time () in
let resultat = f x in
let fin = Sys.time () in
Printf.printf "Calcul effectué en %.3g secondes.\n" (fin -. debut);
flush_all();
resultat
;;
timeit fibo 34 ();;
timeit fibo 36 ();;
Comme avec Python, on peut utiliser Tab
pour afficher de l'aide sur les fonctions de la librairie standard du langage (de l'introspection).
C'est très pratique :
Pour illustrer l'utilisation de ce langage, voyons un exemple issu du tutoriel officiel (https://ocaml.org/learn/tutorials/99problems.html#97-Sudoku-medium) : un solveur de Sudoku.
open Printf
module Board = struct
type t = int array (* 9×9, row-major representation. A value of 0
means undecided. *)
let is_valid c = c >= 1;;
let get (b: t) (x, y) = b.(x + y * 9);;
let get_as_string (b: t) pos =
let i = get b pos in
if is_valid i then string_of_int i else ".";;
let with_val (b: t) (x, y) v =
let b = Array.copy b in
b.(x + y * 9) <- v;
b;;
let of_list l : t =
let b = Array.make 81 0 in
List.iteri (fun y r -> List.iteri (fun x e ->
b.(x + y * 9) <- if e >= 0 && e <= 9 then e else 0) r) l;
b;;
let print b =
for y = 0 to 8 do
for x = 0 to 8 do
printf (if x = 0 then "%s" else if x mod 3 = 0 then " | %s"
else " %s") (get_as_string b (x, y))
done;
if y < 8 then
if y mod 3 = 2 then printf "\n--------+---------+--------\n"
else printf "\n | | \n"
else printf "\n"
done;
flush_all();;
let available b (x, y) =
let avail = Array.make 10 true in
for i = 0 to 8 do
avail.(get b (x, i)) <- false;
avail.(get b (i, y)) <- false;
done;
let sq_x = x - x mod 3 and sq_y = y - y mod 3 in
for x = sq_x to sq_x + 2 do
for y = sq_y to sq_y + 2 do
avail.(get b (x, y)) <- false;
done;
done;
let av = ref [] in
for i = 1 (* not 0 *) to 9 do if avail.(i) then av := i :: !av done;
!av;;
let next (x,y) = if x < 8 then (x+1, y) else (0, y+1);;
(** Try to fill the undecided entries. *)
let rec fill b ((_,y) as pos) =
if y > 8 then Some b (* filled all entries *)
else if is_valid(get b pos) then fill b (next pos)
else match available b pos with
| [] -> None (* no solution *)
| l -> try_values b pos l
and try_values b pos = function
| v :: l ->
(match fill (with_val b pos v) (next pos) with
| Some _ as res -> res
| None -> try_values b pos l)
| [] -> None
;;
end
let sudoku b = match Board.fill b (0,0) with
| Some b -> b
| None -> failwith "sudoku: no solution";;
(* The board representation is not imposed. Here "0" stands for "." *)
let initial_board =
Board.of_list [[0; 0; 4; 8; 0; 0; 0; 1; 7];
[6; 7; 0; 9; 0; 0; 0; 0; 0];
[5; 0; 8; 0; 3; 0; 0; 0; 4];
[3; 0; 0; 7; 4; 0; 1; 0; 0];
[0; 6; 9; 0; 0; 0; 7; 8; 0];
[0; 0; 1; 0; 6; 9; 0; 0; 5];
[1; 0; 0; 0; 8; 0; 3; 0; 6];
[0; 0; 0; 0; 0; 6; 0; 9; 1];
[2; 4; 0; 0; 0; 1; 5; 0; 0]];;
Board.print initial_board;;
Board.print (sudoku initial_board);;
timeit sudoku initial_board ();;
Ce petit notebook montre que la même technologie (les notebooks Jupyter) peut être utilisée pour d'autres langages que Python.
Une très longue liste de kernel existe, avec notamment :