- | none => % if_then_else_ (Sexp_eq ctor (Sexp_symbol "_"))
(quote (##case_ (_|_ (uquote var)
(_=>_ (uquote ctor) (uquote succ)))));
% "?" doesn't seem to help
% (quote (##case_ (_|_ (uquote var)
% (_=>_ (uquote ctor) (uquote succ)))
% (_=>_ _ ?)));
A "%" tout seul c'est pour les commentaires en fin de ligne, pour des commentaires comme ceux-ci, il faudrait utiliser "%%".
[ Si tu édites avec Emacs (en utilisant le mode disponible dans typer/emacs/typer-mode.el), l'indentation automatique (e.g. en pressant TAB) rend ces conventions plus évidentes. ]
Plus sérieusement, il semble qu'il faudra effectivement implémenter un "case" plus optimisé pour éliminer ces problèmes. Je crois qu'on peut le faire sans trop se soucier du := si on suit le principe suivant:
quand on compare X contre en ensemble de motifs, on commence par partitionner ces motifs selon le constructeur principal qu'ils utilisent. Ensuite, pour chaque constructeur qui n'a qu'on seul motif on peut accepter les := sans avoir besoin de savoir à quelle position ils correspondent.
Pour les constructeurs pour lesquels il y a plusieurs motifs, on peut simplement imposer que tous ces motifs utilisent les mêmes :=
Donc on peut accepter
case x | cons (x := foo) bar => ... | cons (x := toto) titi => ... | ...
mais refuser
case x | cons (x := foo) bar => ... | cons toto titi => ... | ...
C'est pas parfait, mais en attendant de faire mieux ça fera l'affaire.
+type Vec2 (a : Type) (b : Type)
- | vec2 a b;
Il vaudrait mieux l'appeler `Pair` comme dans Haskell (et ça pourrait aller dans pervasive.typer remplacer le Pair actuel):
type Pair a b | pair (fst : a) (snd : b);
Tu peux (ou en tout cas, tu devrais pouvoir) ensuite faire:
p = pair 1 2; s = p.fst + p.snd;
+TableData : Type -> Type -> Type;
+type TableData (a : Type) (k : Type)
- | table-node (left : TableData a k) (right : TableData a k)
- | table-leaf (elems : List (Vec2 a k))
- | table-nil;
Au fait, la macro `type` devrait ajouter le "TableData : Type -> Type -> Type;" automatiquement. En fait, il suffit probablement de changer la macro pour qu'elle émette un "TableData : ? -> ? -> Type;".
+%% a : element type +%% k : key type +%% s : size as a base of 2 (e.g. s = 5 <=> size = 32) +%% c : compare function (for key) +%% h : hash function (for key)
Je crois que t'as pas besoin de `s`: tu prends le hash, et sur cette base, tu fais gauche/droite/... bit par bit jusqu'à ce que l'arbre soit vide ou qu'il n'y a plus qu'un seule valeur de hash dans le sous arbre.
Donc pour un arbre contenant 2 valeurs dont les hash respectifs sont 345394 et 119450, tu auras un arbre de la forme:
table-node (left := table-node (table-leaf X) (table-leaf Y)) table-nil
parce que le dernier bit des deux est 0 (donc on va à gauche dans le noeud racine pour les deux) et le bit suivant et 0 d'un côté et 1 de l'autre, donc au niveau suivant l'arbre se termine, vu que chaque sous-arbre ne contient plus qu'une seule entrée.
Je changerais `table-leaf` pour qu'il garde le hash des éléments qu'il porte (devrait être le même pour tous), de manière à éviter de recalculer ce hash autant que possible.
Un autre changement possible serait de n'avoir que `a` (ou que `k`): ça peut être utilisé pour les cas où il n'y pas vraiment de "clé" séparément des données (e.g. quant tu fais tu hash-consing).
Avec une telle Table' tu peux ensuite définir:
Table a k = Table' (Vec2 a k);
pour retrouver la structure que tu as actuellement.
- | table-node l r => ( let
o1 = helper f o l;
o2 = helper f o1 r;
in o2 )
Hmm.... il faudrait peut-être changer la précédence du `in` par rapport à `|` pour ne pas avoir besoin de ces parenthèses?
l2 = if_then_else_ (Int_eq (tabledata-length 0 l1) 0)
(table-nil) (l);
Pourquo n'utilises-tu pas
l2 = if Int_eq (tabledata-length 0 l1) 0 then table-nil else l; ?
r2 = if_then_else_ (Int_eq (tabledata-length 0 r1) 0)
(table-nil) (r);
in table-node l2 r2 )
- | table-leaf xs => if_then_else_ (Int_eq (List_length xs) 0)
(table-nil) (table-leaf xs)
Je trouve cette indentation assez horrible, à vrai dire.
Stefan