Adloun

Probleme – Mutable ou persistant : une pile qu'on peut annuler

Exercice · niveau 3 (difficile) · informatique (MP2I/MPI), chapitre 6 — Types et structures de données abstraites

Énoncé

Corrigé

1. La pile persistante. Elle est déjà écrite : c'est la liste immuable.


module PilePers = struct
  type 'a t = 'a list
  let vide = []
  let empiler x p = x :: p
  let depiler = function [] -> None | x :: r -> Some (x, r)
end

Mesuré, après trois empilages successifs, les quatre versions coexistent :


v0 = []      v1 = [1]      v2 = [2;1]      v3 = [3;2;1]

« Annuler deux fois » consiste à reprendre v1. C'est une opération en qui ne recalcule rien.

2. Le coût de versions, mesuré. On construit versions d'une pile de éléments, une fois par partage et une fois par copie complète, et l'on compte les octets alloués :


100 versions par partage (k :: base) :       3 384 octets
100 copies completes                  :  2 405 784 octets

Un maillon occupe trois mots, soit octets. Les maillons neufs font octets, le tableau qui les tient en fait un millier de plus : le compte est exact. Les copies, elles, allouent octets, à l'octet près.

Le rapport est de , et la raison tient en une phrase : les versions partagent la même queue de maillons, et ce partage est sûr parce que rien n'est modifiable. Chaque version ne paye que ce qui la distingue de la précédente. C'est ce que l'on appelle la persistance, et l'immuabilité en est la condition.

3. Ce que chacune sait faire.

La persistante saitLa mutable sait
garder toutes les versions, donc annuler et refaire en modifier en place, sans allouer un maillon
être partagée entre plusieurs calculs sans copie ni verrouêtre passée à une fonction qui la remplit, l'appelant voyant le résultat
servir de clé, de valeur de retour, d'argument, sans copie défensiveêtre vidée sans laisser de trace en mémoire

La bibliothèque standard offre la seconde sous le nom Stack : create, is_empty, push, pop, et l'exception Stack.Empty — vérifié, un pop de trop lève bien Stack.Empty. Après un pop, l'état antérieur n'existe plus : rien ne le retient.

Le critère de choix n'est donc pas une question de goût. Si l'application a besoin d'un « annuler » — un éditeur, un moteur de jeu qui explore des coups, un analyseur qui revient en arrière —, la structure persistante est la réponse, et elle est bon marché. Sinon, la mutable évite les allocations. Le chapitre chap:jeux rencontrera le premier cas, le chapitre chap:parcours le second.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.