Éléments de syntaxe d'Ocaml

Version & licenses
Creative Commons License

Un peu de syntaxe de base

Guyslain Naves
Définir une variable
  1. (* a : int *)
  2. let a = 42

  3. (* almost_pi : float *)
  4. let almost_pi = 3.14
  5. let google = 1e100
  6. (* Les littéraux flottants se reconnaissent au point ou à l'exposant.
  7. * Les noms de variables se composent avec des _ de préférence
  8. *)

  9. (* cheers : string *)
  10. let cheers = "Hello world!"

  11. (* définition de variables locales a et b *)
  12. let result =
  13. let a = 28 in
  14. let b = 14 in
  15. a + b
Définir une fonction
  1. (* plusieurs syntaxes absolument équivalentes *)
  2. let sum = fun a -> fun b -> a + b (* la forme générale *)
  3. let sum = fun a b -> a + b
  4. let sum a b = a + b (* plus concis et plus lisible *)

  5. (* Il n'est pas nécessaire de donner un nom aux fonctions en Ocaml : *)
  6. let result = (fun x -> 2 * x) 21 (* result = 42 *)

  7. (* pour une fonction récursive, ajouter rec après le let *)
  8. let rec fact n =
  9. if n = 0 then 1
  10. else n * fact (n-1)
Appliquer une fonction
  1. (* une fonction à trois arguments *)
  2. let f x y z = (x + y) * z

  3. let result = f 1 4 3 (* result = 15 *)
  4. let result = f 1 (2 * 2) (f 3 (-2) 3) (* result = 15 *)
  5. (* Les parenthèses délimitent chaque argument individuellement.
  6. * Elles sont nécessaires dès qu'un argument est non-élémentaire.
  7. *)

  8. (* Quelques fonctions *)
  9. let incr x = x + 1
  10. let double x = 2 * x
  11. let mult x y = x * y
  12. (* Et leur utilisation : *)

  13. let a = (* syntaxe parenthésée (suffit en général) *)
  14. mult 3 (double (incr 6))
  15. let a = (* syntaxe avec pipes (pour enchaîner des fonctions) *)
  16. 6
  17. |> incr
  18. |> double
  19. |> mult 3
  20. let a = (* syntaxe avec application explicite *)
  21. mult 3 @@ double @@ incr @@ 6
Utiliser des labels pour les arguments

Avantage désiré : meilleure lisibilité au niveau du code appelant la fonction. Nous utilisons donc les labels dès que nous avons une fonction prenant des arguments nombreux et/ou compliqués, ou pouvant être confondu facilement (par exemple hauteur et largeur). Permet aussi de pouvoir mettre les arguments dans n'importe quel ordre, s'ils sont tous nommés.

  1. (* apply : f:('any -> 'result) -> argument:'any -> 'result *)
  2. let apply ~f ~x = f x
  3. (* Pour créer des arguments avec label, il suffit d'ajouter ~ devant leur nom.
  4. * Attention, pas de ~ dans le type, mais on indique les noms des arguments.
  5. *)

  6. let result = apply ~f:sqrt ~argument:4. (* result = 2.0 *)
  7. (* Pour appliquer la fonction, on indique les labels. *)

  8. let result = apply ~argument:9. ~f:sqrt (* result = 3.0 *)
  9. (* Un avantage est de pouvoir changer l'ordre des arguments *)

  10. let f = sqrt
  11. let argument = 16.
  12. let result = apply ~f ~argument
  13. (* si le label porte le même nom qu'une variable contenant la
  14. * valeur à passer en argument, on l'écrit plus simplement.
  15. *)
Couples et uplets.
  1. let vector = (1.,-2.)
  2. (* La syntaxe [(<expr>,<expr>)] permet de créer un couple *)

  3. let left (x,y) = x
  4. (* la même syntaxe peut être utilisé en place d'un argument,
  5. * pour accéder aux deux valeurs du couple.
  6. *)

  7. let right couple =
  8. let (x,y) = couple in y
  9. (* Ici, [couple] est le nom d'une variable qui contient un couple.
  10. * On peut utiliser une variable locale pour récupérer
  11. * le contenu d'un couple.
  12. *)

  13. (* La même syntaxe s'étend aux triplets, etc. *)
  14. let triplet = ("John", "Doe", 1992)
  15. (* Les couples et triplets peuvent avoir leurs
  16. * composantes de types différents
  17. *)
Les listes

En programmation fonctionnelle, les tableaux ne sont pas une structure fondamentale et élémentaire. Pour coder des ensembles d'éléments, on utilise les listes.

  1. (* :: est l'opérateur d'insertion en début de liste,
  2. * [] est la liste vide.
  3. *)
  4. let ints = 1::2::3::4::[]

  5. (* Pour donner une liste explicitement, une autre syntaxe est possible : *)
  6. let chars = ['a';'b';'c';'d']

  7. (* Attention, la liste suivante ne contient qu'un élément, un triplet *)
  8. let erroneous = ['a','b','c'] (* = [('a','b','c')] *)

  9. (* Les éléments d'une liste doivent être du même type *)
  10. let forbidden = ['a';1;0.0] (* erreur *)

Pour obtenir le contenu d'une liste, il faut utiliser la construction match <expr> with. Souvent, on préfère utiliser les fonctions du module List.

  1. let rec length list =
  2. match list with
  3. | [] -> 0
  4. | first::others -> 1 + length others
  5. (* [first] prend la valeur du premier élément,
  6. * [others] est la liste des éléments suivants
  7. *)