Syntaxe Haskell - Syntaxe C
if e
1then e
2else e
3if (e
1) {e
2; } else {e
3; } e
1? e
2: e
3f x y = e
typeef (
typexx,
typeyy ) {e; }
let x = e
1in e
2{
typexx = e
1; e
2; }
Types en C
•
int, char, short, long, ...•
float, double, ...•
enum•
pointeurs, tableaux, ...•
void•
struct•
union•
fonctionsUn datatype en C
data Type = Atom | Tup Type Type | Arrow Type Type
typedef struct type type;
struct type {
enum { ATOM, TUP, ARROW } tag;
union {
char *atom;
struct { type *t[2]; } tup;
struct { type *t1, *t2; } arrow;
} v;
};
Un datatype en C, suite
#define XTUP(t) ((t)->v.tup)
type *type_tup (type *t1, type *t2) {
type *t = malloc (sizeof (type));
t->tag = TUP;
XTUP (t).t[0] = t1;
XTUP (t).t[1] = t2;
return t;
}
De l’assembleur au C
registres
= ⇒
variables adresses= ⇒
pointeurs +struct+union
+programmation structur ´ee
Programmation imp ´erative
M ˆeme mod `ele que la machine: s ´equence d’op ´erations sur la m ´emoire Les fonctions (qui construisent un r ´esultat) sont remplac ´ees par des proc ´edures (qui op `erent par modification de leurs arguments).
Concepts reli ´es:
•
s ´equence: suite d’op ´erations `a effectuer dans un ordre particulier, avec des d ´ependences implicites•
´etat: ce qui peut changer avec le temps•
effet de bord: modification apport ´ee par une op ´eration•
identit ´e: ce qui distingue un objet d’une copie identique•
valeur: objet sans identit ´eStructure m ´emoire
La m ´emoire est compos ´ee d’un graphe d’objets M ´emoire = un ensemble d’objets
Objet = une s ´equence de bytes
•
Code: ensemble de fonctions et proc ´edures•
Pile: ensemble ordonn ´e d’objets cr ´e ´es implicitement•
Tas: ensemble non-ordonn ´e d’objets cr ´e ´es explicitementProc ´edures
Une fonction ou proc ´edure est un fragment de programme clairement d ´elimit ´e
La signature ou interface d’une fonction est son type Le corps d’une fonction est le code en soi
Une d ´efinition de fonction donne son corps, sa signature, la liste des param `etres formels
Un appel de fonction indique la fonction et les param `etres actuels
Passage de param `etres
Lien entre un param `etre formel et un param `etre actuel
•
par valeur (le plus r ´epandu)•
par nom (Algol, Haskell)•
par r ´ef ´erence (Pascal, C++, Modula-2)•
par valeur-r ´esultat (Ada)Passage par valeur
Le syst `eme le plus simple:
Le param `etre formel est une nouvelle variable, initialis ´ee avec une copie de la valeur du param `etre actuel
Les modifications faites sur le param `etre formel n’affectent pas le param `etre actuel
I.e. l’appel ´e ne peut pas avoir d’effet sur l’appelant
Passage par nom
Le param `etre actuel est une expression pass ´ee sans ˆetre ´evalu ´ee Le param `etre formel fait r ´ef ´erence `a l’expression
Chaque usage du param `etre formel cause l’ ´evaluation de l’expression
Passage par r ´ef ´erence
Le param `etre actuel est un emplacement m ´emoire Le param `etre formel d ´esigne le m ˆeme emplacement
PROCEDURE inc (VAR x : integer) BEGIN
x = x + 1;
END
... inc (z); inc (y[3]); ...
On peut parfois le simuler en passant par valeur une r ´ef ´erence:
void inc (int *x) { *x = *x + 1; }
... inc (&z); inc (y+3); ...
Passage par valeur-r ´esultat
A mi-chemin entre passage par valeur et passage par r ´ef ´erence Le param `etre actuel est un emplacement m ´emoire
le param `etre formel est une nouvelle variable initialis ´ee avec la valeur contenue dans l’emplacement m ´emoire
Lorsque la fonction termine, la valeur du param `etre formel est copi ´ee dans l’emplacement du param `etre actuel
On peut aussi le simuler en passant par valeur une r ´ef ´erence:
void inc (int *xp)
{ int x = *xp; x = x + 1; *xp = x; }
... inc (&z); inc (y+3); ...
Alias
alias: deux mani `ere diff ´erentes de nommer une m ˆeme entit ´e
Example:
FUNCTION foo (VAR a : INTEGER) BEGIN ... END ... foo (b); ...
Ou encore:
XAPP (e1).f = XTUP (e2).e1;
Ou encore:
let x = (snd y, y) in ...
Alias, suite
Une modification sur un objet affecte imm ´ediatement tous ses alias Peut- ˆetre tr `es utile
Mais c’est aussi une source de probl `emes difficiles
Sans alias, passage par r ´ef ´erence
≡
passage par valeur-r ´esultat La notion d’alias est intimement li ´ee `a celle de pointeurint foo (int x[], int y[]) { x[0] = 1;
y[0] = 2;
return x[0] + y[0]; }
Pointeurs et r ´ef ´erences
Tout probl `eme peut ˆetre r ´esolu en ajoutant un niveau d’indirection Utilis ´es de mani `ere interne par les compilateurs
Utilis ´es pour les structures de donn ´ees plus complexes que les tableaux et les enregistrements
Taille fixe (petite) ind ´ependante de l’objet r ´ef ´erenc ´e Utilis ´e aussi pour ´eviter des copies co ˆuteuses
∗x '
mem[x]
Op ´erations sur les pointeurs
Op ´erations principales:
•
Allocation d’un objet, renvoie un nouveau pointeur sur un espace m ´emoire jusqu’alors inutilis ´e•
Indirection, pour acc ´eder `a l’objet point ´e par le pointeur•
R ´ecup ´eration de l’espace allou ´e Autres op ´erations parfois support ´ees:•
Arithm ´etique:p + n
,p
1− p
2, ...•
Obtention d’un pointeur sur un objet existant:&x
Arithm ´etique sur les pointeurs
En C, on peut additionner un pointeur et un entier
∗(x + n) '
mem[x + n ∗ k]
C’est utilis ´e pour les tableaux:
x[n] ≡ ∗(x + n) ≡ ∗(n + x) ≡ n[x]
Si
x
pointe sur un tableau de taille 10, la valeur dex + 11
est ind ´efinie On peut aussi faire la diff ´erence entre 2 pointeurs:(x + n) − x == n
La valeur de
x
1− x
2 n’est pas d ´efinie six
1 etx
2 pointent dans des objets diff ´erentsStructures de contr ˆ ole
flux/flot de contr ˆole = trajet suivi par le point d’ex ´ecution flux/flot de donn ´ee = trajet suivi par les donn ´ees
•
Sauts:goto
,break
,continue
, ...•
Tests:if
,case
, filtrage,? :
,&&
,||
, ...•
Boucles:for
,while
,loop
, ...•
Fonctions•
Exceptions•
Non-d ´eterminismeFonctions d’ordre sup ´erieur
Les fonctions d’ordre sup ´erieur permettent de cr ´eer de nouvelles structures de contr ˆole
fun
fora b f =
if a > b then ()
else (f a;
for(a + 1) b f ) . . .
for
1 10 ( fn i ⇒
print(
Int.toStringi))
Programmation structur ´ee
L’usage abusif de
goto
m `ene `a des programmes spaghettiLa programmation structur ´ee impose des r `egles qui assurent une
certaine correspondance entre la structure syntaxique d’un programme et son flot de contr ˆole
Structuration stricte: un point d’entr ´ee et un point de sortie Structuration laxiste: un point d’entr ´ee
Le switch de C
L’ ´enonc ´e switch de C n’est pas tr `es structur ´e
void copier (char *src, char *dst, int n) { while (n > 0) { *dst++ = *src++; n--; } }
void copier (char *src, char *dst, int n) { switch (n & 3) {
case 0: while (n > 0) { *dst++ = *src++;
case 3: *dst++ = *src++;
case 2: *dst++ = *src++;
case 1: *dst++ = *src++;
n -= 4;
} } }
R ´ecursion
La r ´ecursion est une forme g ´en ´eralis ´ee de boucle
void toto ()
{
int c, fdl;
fdl = TRUE;
while ((c = getchar ()) != EOF) { if (c == ’\n’) {
if (fdl) continue;
fdl = TRUE;
} else
fdl = FALSE;
putchar (c);
R ´ecursion (suite)
void toto_1 (int fdl) {
int c;
if ((c = getchar ()) != EOF) { if (c == ’\n’) {
if (fdl) continue;
fdl = TRUE;
} else
fdl = FALSE;
putchar (c);
toto_1 (fdl);
} }
R ´ecursion (continue)
if ((c = getchar ()) != EOF) { if (c == ’\n’ && fdl)
toto_1 (fdl);
else {
if (c == ’\n’) fdl = TRUE;
} else
fdl = FALSE;
putchar (c);
toto_1 (fdl);
} }
R ´ecursion (nettoyage)
void toto_1 (int fdl) {
int c = getchar ();
if (c != EOF) {
if (c == ’\n’ && fdl) toto_1 (TRUE);
else {
putchar (c);
toto_1 (c == ’\n’);
} } }
void toto () { toto_1 (TRUE); }
R ´ecursion (fin)
void toto_1 (int fdl) {
int c = getchar ();
if (c != EOF) {
if (c != ’\n’ || !fdl) putchar (c);
toto_1 (c == ’\n’);
} }
void toto () { toto_1 (TRUE); }
Repr ´esentation des objets scalaires
Les objets tels que: pointeurs, entiers, caract `eres, bool ´eens,
enum
, nombres `a virgule flottante, ...G ´eneralement trait ´es de mani `ere atomique Pas de notion d’identit ´e
Repr ´esent ´es par un nombre fixe de bits
Contraintes d’alignement, soit impos ´ees par l’architecture, soit n ´ecessaires pour des raisons de performance
Alignement naturel = adresse est un multiple de la taille de l’objet
Repr ´esentation des tableaux
Noms: tableaux, vecteurs
Disposition contigu ¨e en m ´emoire
Chaque ´el ´ement du tableau a la m ˆeme taille adresse de
T [i] =
base+ (i −
min) ×
sizeSelon les langages, la repr ´esentation peut ou non contenir un champ suppl ´ementaire qui indique la taille totale du tableau
Sans ce champ suppl ´ementaire le compilateur ne peut pas v ´erifier les d ´epassements de bornes
Repr ´esentation des structures
Les noms varient: structures, enregistrements, objets, tuples, ...
Dispositions contigu ¨e des champs en m ´emoire:
record
a : char; (* adr relative = 0 *)
b1,b2 : integer; (* adr relative = 1 et 5 *) c : real; (* adr relative = 9 *)
end
En r ´ealit ´e, du padding sera ajout ´e pour aligner le champ
b1
, doncl’adresse relative de
b1
,b2
, etc
sera respectivement 4, 8, et 12 Du padding peut ausi ˆetre ajout ´e `a la finEffets de bord en Haskell
Probl `eme:
•
D ´eterminer si une expression est ´evalu ´ee, combien de fois, et dans quel ordre, peut ˆetre tr `es difficile en Haskell.•
Heureusement, cela ne change rien au r ´esultat.•
Par contre, cela rend les effets de bord inutilisables.Solution: main renvoie une liste de commandes `a ex ´ecuter.
L’ex ´ecution de ces commandes est faite “en dehors”.
IO τ
: type d’une commande qui renverra une valeur de typeτ
.Entr ´ees sorties en Haskell
getChar :: IO Char
putChar :: Char -> IO ()
L’op ´erateur
>>=
permet de composer les op ´erations:(>>=) :: IO a -> (a -> IO b) -> IO b
getChar >>= (\c -> putChar (succ c)) :: IO ()
Cela s’ ´ecrit habituellement avec le sucre syntaxique
do
:do c <- getChar
putChar (succ c)
Affectations en Haskell
En plus de toutes les structures de donn ´ees pures, Haskell a aussi des cellules sp ´eciales que l’on peut modifier `a loisir:
newIORef :: a -> IO (IORef a) readIORef :: IORef a -> IO a
writeIORef :: IORef a -> a -> IO ()
newIORef v
cr ´ee une nouvelle cellule muable initialis ´ee `av readIORef r
lit le contenu de la celluler
writeIORef r v
affecte `a la celluler
la valeurv
Distinguer une commande et son ex ´ecution
La partie pure du langage est s ´epar ´ee de la partie impure
a = map putChar [’a’, .. ’z’]
b = (a,a)
c = putChar ’1’
main = head (snd b)
a
est une liste de commandesb
est une paire de 2 listes de commandes Le programme imprime seulement “a
”Monads et effets
IO
est un monad•
Il y en a beaucoup d’autres (ST, Maybe, Cont, Parser, List, STM, ...)•
Le monad indique quel genre d’effet peut ˆetre pr ´esent dans la commande correspondante.Dans les langages imp ´eratifs, il existe un concept similaire: les syst `emes d’effets