TP 1 - Introduction a CaML Light

 

CaML: (Categorical abstract Machine Language) est un langage de programmation fonctionnelle. La programmation fonctionnelle est un style de programmation où un programme est structuré en terme d'application de fonctions mathématiques. Caml light est une implémentation "legère" de Caml.

Pour telecharger CamlLight IDE aller a la PAGE..

 

3- Les Types de Base en Caml

Il y'a 5 types de base en Caml: les entiers, les réels, les booléens, les caractères et chaines de caractères, et les tuples.

Une expression doit etre terminée par ";;" pour que l'interpreteur Caml évalue l'expression.

 

Evaluer les Expressions Entières Suivantes:

======================================

Un entier (int) est une valeur comprise entre -1073741824 et 1073741823.

 

212;; 12/4;; 276 mod 23;;   21 + 23+ 17 + 3;;  4 * 91;;  10 / 6;;

(3 * 5) + (10 - 6);;  2.7 + 10;;  int_of_float 2.1;;  float_of_int 16;;

max 4 8;; min (-4) (-8);; abs 8; abs (-8);; succ 3;; pred 9;; succ (-3);; pred (-8);;

 

 

#212;;

- : int = 212

#

 

#12/4;;

- : int = 3

#

 

#276 mod 23;;

- : int = 0

#

 

#21 + 23+ 17 + 3;;

- : int = 64

#

 

#4 * 91;;

- : int = 364

#

 

#10 / 6;;

- : int = 1

#

 

#(3 * 5) + (10 - 6);;

- : int = 19

#

 

 

 

#2.7 + 10;;

Toplevel input:

>2.7 + 10;;

>^^^

This expression has type float,

but is used with type int.

 

#int_of_float 2.1;;

#- : int = 2

#

 

#float_of_int 16;;

- : float = 16.0

#

 

#max   4   8;;

- : int = 8

#

 

#min (-4) (-8);;

- : int = -8

#

 

#abs 8;;

- : int = 8

 

#

#abs (-8);;

- : int = 8

#

 

#succ 3;;

- : int = 4

#pred 9;;

- : int = 8

#succ (-3);;

- : int = -2

#pred (-8);;

- : int = -9

#

 

Evaluer les Expressions Réelles Suivantes:

===================================

3.45;;  10.0 /. 6.0;;  1.1 +. 2.2;; ceil 3.14;; floor 3.14;; exp 1.0;; 

log 2.71828182846;;  3. ** 2.;; 3.45e10;; sqrt 25.;; abs_float 4.2;; abs_float (-4.2);;

max 4.5 8.5;;  min (-4.5) (-8.5);;

 

Remarque:

On ne peut pas utiliser les opérations +, -, * et / sur les réels; il faut utiliser les opérations notées: +., -., *. et /.

On ne peut pas mélanger entier et réel en Caml. Il faudra convertir les entiers en réel (float_of_int) ou bien convertir les réels en entiers (int_of_float).

 

#3.45;;

- : float = 3.45

#

 

#10.0 /. 6.0;;

- : float = 1.66666666667

#

 

#1.1 +. 2.2;;

- : float = 3.3

#

 

#ceil 3.14;;

- : float = 4.0

#

 

 

#floor 3.14;;

- : float = 3.0

#

 

#exp 1.0;;

- : float = 2.71828182846

#

#log 2.71828182846;;

- : float = 1.0

 

#3. ** 2.;;

- : float = 9.0

#

 

#3.45e10;;

- : float = 34500000000.0

#

 

#sqrt 25.;;

- : float = 5.0

#

 

#abs_float 4.2;;

- : float = 4.2

 

 

#abs_float (-4.2);;

- : float = 4.2

#

 

#max 4.5 8.5;;

- : float = 8.5

#

 

#min (-4.5) (-8.5);;

- : float = -8.5

#

 

Evaluer les Expressions Booléennes Suivantes:

========================================

true;; not true;; true && false;; true || false;; true or false;; 

1<2;; 1<=2;; 0<1  & 3<9;; (not false) or true;; "un"<"deux";;

 

#true;;

- : bool = true

#

#not true;;

- : bool = false

#

 

#true && false;;

- : bool = false

#

 

#true || false;;

- : bool = true

#

 

#true or false;;

- : bool = true

#

 

#1<2;;

- : bool = true

#

 

#1<=2;;

- : bool = true

#0<1  & 3<9;;

- : bool = true

#(not false) or true;;

- : bool = true

#

#"un"<"deux";;

- : bool = false

#

 

Evaluer les Expressions Caractères et Chaines de Caractères Suivantes:

=============================================================

 

`a`;; int_of_char `a`;; char_of_int 97;; "a";; "ceci est une c" ^ "haine de caracteres!";;

"toutou".[5];; "kArim".[1];; string_length "KADER";; sub_string "Bonjour" 0 3;;

 

 

`a`;;

- : char = `a`

#int_of_char `a`;;

- : int = 97

#char_of_int 97;;

- : char = `a`

#"a";;

- : string = "a"

#"ceci est une c" ^ "haine de caracteres!";;

#- : string = "ceci est une chaine de caracteres!"

#"toutou".[5];;

#- : char = `u`

#"kArim".[1];;

#- : char = `A`

#string_length "KADER";;

#- : int = 5

#sub_string "Bonjour" 0 3;;

#- : string = "Bon"

#

#`a`;;

- : char = `a`

#string_of_char `a`;;

- : string = "a"

 

Remarques:

int_of_char: retourne le code ascii en décimal du caractère

char_of_int: retourne le caractère du code ascii donné

^: fait la concaténation de 2 chaines de caractères

ch.[i]: retourne le caractère d'indice i de la chaine ch (les indices commencent de 0 ch.[0] retourne le premier caractère)

string_length ch: retourne le nombre de caractères de la chaine ch

sub_string ch i l: retourne la chaine commençant à partir du caractère d'indice i et ayant l caractères

 

Noter les équivalences suivantes entre Caml light et OCaml: 

      Caml Light                                               Equivalent en OCaml

     string_length                                                String.length

     sub_string                                                      String.sub

     string_of_char                                              Char.escaped

 

Evaluer les Expressions Tuples Suivantes:

====================================

Tuples: combinaison de valeurs pour former des paires, triplets, quadruplets, ...

Tuple: composants l'un à la suite de l'autre separés par "," avec des parenthèses  (pour augmenter la lisibilité mais ne sont pas nécessaires). Le type d'un tuple est le type de ces composants separés par une "  *".

 

(1,2);; 1,2,3;; (1, (2,3));; (12, "October");; ("coucou", 1.2, (`A`,2));;

 

fst(12, "October");; snd(12, "October");; (12, "october", true);;

 

Remarque:

Pour les tuple pairs: 

fst(p1, p2) retourne p1

snd(p1, p2) retourne p2

 

#(1,2);;

- : int * int = 1, 2

#1,2,3;;

- : int * int * int = 1, 2, 3

#(1, (2,3));;

- : int * (int * int) = 1, (2, 3)

#(12, "October");;

- : int * string = 12, "October"

#("coucou", 1.2, (`A`,2));;

- : string * float * (char * int) = "coucou", 1.2, (`A`, 2)

#fst(12, "October");;

- : int = 12

#snd(12, "October");;

- : string = "October"

#(12, "october", true);;

- : int * string * bool = 12, "october", true

 

4. Les Opérateurs de Comparaison en Caml 

Les opérateurs suivants s'appliquent aux entiers, aux réels, aux caractères ainsi que pour les chaines de caractères. Une comparaison utilisant un des symboles ci-dessous ne doit concerner que 2 objets de même type:

    >     : Superieur

    >=   : Superieur ou Egale

    <      : Inferieur

    <=    : Inferieur ou Egale

     =     : Egalite

     <>   : Different

 

 

 

Les opérateurs suivants (Noter le point '.' a la fin) s'appliquent uniquement aux réels:

    >.     : Superieur

    >=.   : Superieur ou Egale

    <.      : Inferieur

    <=.    : Inferieur ou Egale

     =.     : Egalite

     <>.   : Different

 

Remarques:

1) Pour les caractères on a suivant le code ASCII (ordre lexicographique):

    ...< '0' < '1' < '2' < ... <'9'< . . . <'A' < 'B' < 'C' < ... <'Z'< . . . <'a' < 'b' < 'c' ... <'z' < ... 

 

Le caractère '0' a le code ascii 48, le caractère '1' a le code ascii 49, ..., le caractère '9' a le code ascii 57

Le caractère 'A' a le code ascii 65, le caractère 'B' a le code ascii 66, ..., le caractère 'Z' a le code ascii 90

Le caractère 'a' a le code ascii 97, le caractère 'b' a le code ascii 98, ..., le caractère 'z' a le code ascii 122

 

2) Les chaines de caractères sont comparées selon l'ordre lexicographique.

La chaine vide "" est < à toutes les autres chaines.

Si on a 2 chaines A et B tels que: A = "a1a2a ... am" (m caractères) et B = "b1b2 ... bn" (n caractères) alors:

A < B              si:    'a1' < 'b1'  ou  ('a1' = 'b1' et "a2a3 ... am"  < "b2b3 ... bn")

A > B              si:    'a1' > 'b1'  ou  ('a1' = 'b1' et "a2a3 ... am"  > "b2b3 ... bn")

A = B              si:    'a1' = 'b1'   et "a2a3 ... am"  = "b2b3 ... bn"  (c'est à dire exactement le même nombre de caractères (m=n) et exactement les même caractères dans le meme ordre).

 

3) Il existe aussi en Caml les 2 opérateurs: == et != (negation de ==).

L'opérateur == teste l'égalite physique des valeurs (identité des adresses mémoire en cas de valeurs allouées). Il faut faire attention à l'usage de ces 2 opérateurs dans le cas des chaines de caractères et des réels. On utilisera uniquement les opérateurs "=" et "<>" dans les TPs qui suivent pour tester l'egalité et l'inegalité.

 

5. Le Type unit, les Impressions et les lectures du clavier en Caml 

Pour afficher une expression en Caml, les fonctions prédefinies: print_int, print_float, print_char et print_string permettent cela.  Ces fonctions prennent un entier, un réel, un caractère ou une chaine de caractères et affichent cet argument mais ne produisent pas de résultat: ceci est exprime par le type unit qui signifie qu'il n'y a pas de résultat (unit est un peu l'équivalent de void en C).

Pour lire du clavier les fonctions prédefinies:  read_int, read_float et read_line permettent de lire respectivement un entier, un réel ou une chaine de caractères.

 

#print_int;;

- : int -> unit = <fun>

#print_float;;

- : float -> unit = <fun>

#print_char;;

- : char -> unit = <fun>

#print_string;;

- : string -> unit = <fun>

#

 

#let x = 12;;

x : int = 12

#print_int x;;

12- : unit = () 

 

# read_int;; 

- : unit -> int = <fun>

 

# read_float;;

- : unit -> float = <fun>

 

#read_line;;

- : unit -> string = <fun>

 

#let x = read_int();;

15

x : int = 15

#print_int    x;;

15- : unit = ()

 

#let x = read_float();;

18.7

x : float = 18.7

#print_float    x;;

18.7- : unit = ()

 

#let x = read_line();;

abcdef ghi

x : string = "abcdef ghi"

#print_string    x;;

abcdef ghi- : unit = ()

 

6. Définition

Une définition est une déclaration qui associe un nom à une expression. Il y'a 2 types de déclarations: les déclarations globales et les déclarations locales.

 

6.1 Déclaration Globale

Syntaxe:

      let nom = expression;;

ou nom représente l'identificateur et expression l'expression qui lui est associée.

 

Exemple: 

#let x = 12;;

x : int = 12

#x;;

 

- : int = 12

Remarque: Caml est case sensitive. Les noms en minuscule ne sont pas les même que les noms en majuscule.

 

 

#X;;

Toplevel input:

>X;;

>^

The value identifier X is unbound.

#

 

Déclarations Globales Simultanées

Syntaxe

  let nom1 = expression1

      and

      nom2 = expression2

      and ...

      nomn = expressionn;;

 

Exemple: 

#let x = 2 and y = 5;;

x : int = 2

y : int = 5

#

 

#let x = 4;;

x : int = 4

#

#x+3;;

- : int = 7

#

 

#let x =5.8;;

x : float = 5.8

#

#x +. 3.1;;

- : float = 8.9

 

#

 

 

 

#let a=3 and b=4;;

a : int = 3

b : int = 4

#a+b;;

- : int = 7

 

6.2 Déclaration Locale

Syntaxe:

let nom = expression1 in expression2;;

 

Exemple:

#let x = 6 in x * x;;

- : int = 36

#

 

Déclarations Locales Simultanées

Syntaxe

  let nom1 = expression1

      and

      nom2 = expression2

      and ...

      nomn = expressionn

  in expression;; 

 

Exemple:

 

#let x=(1, "coucou") and y=("hello", 2.1) in (snd x, fst y);;

- : string * string = "coucou", "hello"

#

 

let a=1 and b=2*a in a+b;;

- : int = 7

#

 

Noter dans l'expression ci-dessus le a locale égale à la valeur 1 est connu et utilisé (apres le in) dans l'expression a+b mais dans la déclaration b=2*a c'est le a globale qui est utilisé (le a locale est connu uniquement après le in). Le a globale a été declaré avec la valeur 3 dans l'exemple auparavant (expression let a=3 and b=4;;).

 

let a= (let b=2 in 6+b);;

a : int = 8

#

 

#let a =1 in let b=2*a in b + a;;

- : int = 3

#

 

Par contre dans l'exemple ci-dessus le a locale est connu après le in; donc c'est le a locale qui a la valeur 1 qui est utilisé dans let b=2*a (et aussi dans b+a).

 

6.3 If Statement

Syntaxe:

     if expBoolean then exp1 else exp2;;

 

La valeur de cette expression est exp1 si expBoolean s'evalue à Vrai (True); 

sinon c'est exp2 (expBoolean s'evalue dans ce cas à Faux :False).

Remarque: Il faut que exp1 et exp2 soient de même type.

 

If sans clause else.

Syntaxe:

   if expBoolean then exp;;

 

Un if sans clause else correspondante est automatiquement completé par une clause else (). Comme else () a le type unit il faut dans ce cas que exp soit aussi de type unit. Ce genre de construction est utilisé par exemple dans le cas où on fait une impression. Comme par exemple:

#let x = 13;;

x : int = 13

#if x>0 then print_int x;;

13- : unit = ()

#

 

Exemples de if statement

 

#if true then 1 else 0;; 

- : int = 1

#

 

#(if 3=5 then 8 else 10) + 6;;

- : int = 16

#

 

#let x=3 in if x=0 then 0 else 15/x;;

- : int = 5

#

 

#(if 3=5 then 8 else 10) + 6;;

- : int = 16

#let x=3 in if x=0 then 0 else 15/x;;

- : int = 5

 

#let x=3 in let y=2 in x + y;;

- : int = 5

#

 

Exercice: Evaluer dans cet ordre les expressions suivantes:

 

let x = 2 in x * x;;

x;;

let x = 12;;

x;;

let x = 4 and y = 5 in x + y;;

x;;

y;;

let y = (let x = 3 and z = 8 in x * z);;

x;;

y;;

z;;

let z = (if x=y then "XEgaleY" else "XDifferentY");;

z;;

x;;

y;;

let x = (if y>0 then "YPositif" else "YNonPositif");;

x;;

let w1 = (let a1=("12", "Douze") and a2=("13", "Treize") and a3=("14", "Quatorze") in

          (fst a1 ^ fst a2 ^ fst a3, snd a1 ^ " " ^ snd a2 ^ " " ^ snd a3));;

 

let w2 = (let a1=("12", "Douze") and a2=("13", "Treize") and a3=("14", "Quatorze") in

          (fst a1 ^ snd a2 ^ fst a3, snd a1 ^ fst a2  ^ fst a3, fst a1 ^ fst a2 ^ snd a3));;

 

let w3 = (let a1=12 and a2=13 and a3=14 in (string_of_int a1 ^ string_of_int a2 ^ string_of_int a3, max a1 (min a2 a3)));;

 

w3;;

w1;;

let w4 = (let l = string_length (fst w1 ^ snd w1) and w5 = (fst w1 ^ snd w1) in (w5, l));;

 

let w5 = (let l = string_length (fst w4) and w6 = (fst w4) in (w6.[0], w6.[l - 1]));;

w5;;

let w6 = (let l = string_length (snd w1) and w5 = snd w1 in 

           if l>10 then sub_string w5 10 (l - 10) else sub_string w5 0 (l - 1));;

w6;;

let w7 = (let l = string_length (fst w1) and w5 = fst w1 in 

           if l>10 then sub_string w5 10 (l - 10) else sub_string w5 0 (l - 1));;

w7;;

let x1 = 3 and x2 = x1 + 1 in x1 + x2;;

let x1 = 3 in let x2 = x1 + 1 in x1 + x2;;

let x1 = 11;;

let x1 = 3 and x2 = x1 + 1 in x1 + x2;;

 

Solution