| Anonymous | Login | Signup for a new account | 2013-05-20 05:35 CEST | ![]() |
| Main | My View | View Issues | Change Log | Roadmap |
| View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||||
| ID | Project | Category | View Status | Date Submitted | Last Update | ||||||
| 0001231 | OCaml | OCaml general | public | 2002-07-10 16:00 | 2002-07-11 17:11 | ||||||
| Reporter | administrator | ||||||||||
| Assigned To | |||||||||||
| Priority | normal | Severity | feature | Reproducibility | always | ||||||
| Status | acknowledged | Resolution | open | ||||||||
| Platform | OS | OS Version | |||||||||
| Product Version | |||||||||||
| Target Version | Fixed in Version | ||||||||||
| Summary | 0001231: Feature wish: better pretty-printing for cyclic values | ||||||||||
| Description | Hello, l'affichage d'une valeur circulaire (créée avec un let rec ou avec des effets de bords) dans le toplevel n'est pas très satisfaisante: il ne termine que parce que le pretty-printer s'arrête à une certaine profondeur. On peut imaginer de detecter les boucles comme pour les types récursifs et de les briser en introduisant des alias, par exemple: type t = { x : int; mutable y : t option };; let a = { x = 10; y = None };; a.y <- Some a;; a;; donnerait: { x = 10; y = Some #a } as #a ou peut-être: #a where #a = { x = 10; y = Some #a} (ou n'importe quelle autre syntaxe pour les «variables de valeurs»). La deuxième possibilité permet parfois d'y voir plus clair lorsqu'il y a des boucles imbriquées, si on autorise la forme plus générale: v where #a1 = v1 and ... and #an = vn. Par exemple, pour let rec x = 1 :: y and y = 2 :: x in (x,y) : (#a, #b) where #a = 1 :: #b and #b = 2 :: #a (pour les listes, il faudrait renoncer aux crochets, et utiliser explicitement le constructeur (::)) Un affichage soigné des valeurs cycliques serait très appréciable lorsque l'on fait dans le toplevel la mise au point d'algorithmes sur des graphes. Je ne vois pas vraiment de difficultés techniques. Est-ce que vous envisagez d'implémenter ce genre de chose ? -- Alain | ||||||||||
| Tags | No tags attached. | ||||||||||
| Attached Files | |||||||||||
Notes |
|
|
(0000131) administrator (administrator) 2002-07-10 17:41 |
> On peut imaginer de detecter les boucles comme pour les types récursifs > et de les briser en introduisant des alias, par exemple: [...] > type t = { x : int; mutable y : t option };; > let a = { x = 10; y = None };; > a.y <- Some a;; > a;; > > > donnerait: > > { x = 10; y = Some #a } as #a > > ou peut-être: > > #a where #a = { x = 10; y = Some #a} > > (ou n'importe quelle autre syntaxe pour les «variables de valeurs»). > > La deuxième possibilité permet parfois d'y voir plus clair > lorsqu'il y a des boucles imbriquées, si on autorise la forme > plus générale: v where #a1 = v1 and ... and #an = vn. > Par exemple, pour let rec x = 1 :: y and y = 2 :: x in (x,y) : > > (#a, #b) where #a = 1 :: #b and #b = 2 :: #a > > (pour les listes, il faudrait renoncer aux crochets, et utiliser > explicitement le constructeur (::)) > > > Un affichage soigné des valeurs cycliques serait très appréciable lorsque > l'on fait dans le toplevel la mise au point d'algorithmes sur des graphes. > Je ne vois pas vraiment de difficultés techniques. Est-ce que vous > envisagez d'implémenter ce genre de chose ? Le coût de détection des cycles n'est évidemment pas nul, même s'il est supportable en pratique. D'habitude (dans les anciennes implémentations de Caml qui avaient ce trait), on écrivait t0 where t0 = ... and t1 = ... où t était le nom du type concerné. On pourrait maintenant plutôt écrire let rec t0 = ... and t1 = ... in t0 Qui aurait aussi l'avantage d'être un programme Caml légal... Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ [^] |
|
(0000132) administrator (administrator) 2002-07-10 19:19 |
On Wed, 10 Jul 2002, Pierre Weis wrote: > Le coût de détection des cycles n'est évidemment pas nul, même s'il > est supportable en pratique. Oui ! Mais de toute manière, il y a une limite à la taille de la valeur affichée, donc le surcout est une constante. > D'habitude (dans les anciennes implémentations de Caml qui avaient ce > trait), on écrivait > > t0 where t0 = ... and t1 = ... Ah tiens, pourquoi ça a changé ? J'ai justement choisi cette notation pour mon language CDuce; les types récursifs me semblent beaucoup plus lisibles ainsi. > où t était le nom du type concerné. On pourrait maintenant plutôt > écrire > > let rec t0 = ... and t1 = ... in > t0 > > Qui aurait aussi l'avantage d'être un programme Caml légal... Comme une demande a toujours plus de poids quand on envoie du code avec, voici un patch par rapport à la version CVS: Index: toplevel/genprintval.ml =================================================================== RCS file: /caml/ocaml/toplevel/genprintval.ml,v retrieving revision 1.31 diff -r1.31 genprintval.ml 176c176,199 < let rec tree_of_val depth obj ty = --- > let counter = ref 0 in > let named = ref [] in > let new_name result = > incr counter; > let name = "v" ^ string_of_int !counter in > named := (name,result) :: !named; > name in > > let rec tree_of_val visited depth obj ty = > try > let (alias,result) = List.assq obj visited in > let name = match !alias with > | Some x -> x > | None -> > let x = new_name result in > alias := Some x; > x > in > Oval_stuff name > with Not_found -> > begin > let myname = ref None in > let mytree = ref None in > let visited = (obj, (myname,mytree)) :: visited in 182a206 > let result = 189c213 < Oval_tuple (tree_of_val_list 0 depth obj ty_list) --- > Oval_tuple (tree_of_val_list 0 visited depth obj ty_list) 191c215 < tree_of_exception depth obj --- > tree_of_exception visited depth obj 203c227 < tree_of_val (depth - 1) (O.field obj 0) ty_arg in --- > tree_of_val visited (depth - 1) (O.field obj 0) ty_arg in 223c247 < tree_of_val (depth - 1) (O.field obj i) ty_arg in --- > tree_of_val visited (depth - 1) (O.field obj i) ty_arg in 233c257 < then let v = tree_of_val depth (Lazy.force (O.obj obj)) ty_arg in --- > then let v = tree_of_val visited depth (Lazy.force (O.obj obj)) ty_arg in 243c267 < tree_of_val depth obj --- > tree_of_val visited depth obj 260c284 < constr_name 0 depth obj ty_args --- > constr_name 0 visited depth obj ty_args 276c300 < tree_of_val (depth - 1) (O.field obj pos) --- > tree_of_val visited (depth - 1) (O.field obj pos) 298c322 < tree_of_val (depth - 1) (O.field obj 1) ty in --- > tree_of_val visited (depth - 1) (O.field obj 1) ty in 316c340 < tree_of_val (depth - 1) obj ty --- > tree_of_val visited (depth - 1) obj ty 320c344 < tree_of_val (depth - 1) obj ty --- > tree_of_val visited (depth - 1) obj ty 322a347,350 > in > match !myname with > | Some x -> mytree := Some result; Oval_stuff x > | None -> result 323a352 > end 325c354 < and tree_of_val_list start depth obj ty_list = --- > and tree_of_val_list start visited depth obj ty_list = 329c358 < let tree = tree_of_val (depth - 1) (O.field obj i) ty in --- > let tree = tree_of_val visited (depth - 1) (O.field obj i) ty in 334c363 < tree_of_cstr cstr_name start depth obj ty_args = --- > tree_of_cstr cstr_name start visited depth obj ty_args = 336c365 < let args = tree_of_val_list start depth obj ty_args in --- > let args = tree_of_val_list start visited depth obj ty_args in 339c368 < and tree_of_exception depth bucket = --- > and tree_of_exception visited depth bucket = 355c384 < (fun x -> Oide_ident x) name 1 depth bucket cstr.cstr_args --- > (fun x -> Oide_ident x) name 1 visited depth bucket cstr.cstr_args 361c390,398 < in tree_of_val max_depth obj ty --- > in > let result = tree_of_val [] max_depth obj ty in > let named = > List.rev_map > (function (x,{contents=Some y}) -> (x,y) > | _ -> assert false) > !named in > Oval_aliases (result, named) > Index: typing/oprint.ml =================================================================== RCS file: /caml/ocaml/typing/oprint.ml,v retrieving revision 1.7 diff -r1.7 oprint.ml 52a53,57 > | Oval_aliases (v, b) -> > if b = [] > then print_simple_tree ppf v > else fprintf ppf "@[<1>let rec@ %a@ in@ %a@]" print_aliases b > print_tree_1 v 53a59,65 > and print_aliases ppf = function > | [ (name,alias) ] -> > fprintf ppf "@[<1>%s@ =@ %a@]" name print_tree_1 alias > | (name,alias) :: r -> > fprintf ppf "@[<1>%s@ =@ %a@ and@ %a@]" name print_tree_1 > alias print_aliases r > | [] -> assert false Index: typing/outcometree.mli =================================================================== RCS file: /caml/ocaml/typing/outcometree.mli,v retrieving revision 1.7 diff -r1.7 outcometree.mli 42a43 > | Oval_aliases of out_value * (string * out_value) list Notes: - les alias sont tous introduits au niveau supérieur - les chaines de formattage pourraient être mieux écrites - pas de traitement particulier pour les listes (il en faudrait) - ça ne met en évidence que les égalités physiques entre une valeur et celles qui sont accessibles à partir de celle-ci, donc: # let rec x = (x,y) and y = (y,x) in (x,y);; - : ('a * ('b * 'a as 'b) as 'a) * ('c * ('d * 'c as 'd) as 'c) = let rec v1 = (v1, v2) and v2 = (v2, v1) and v3 = (v3, v4) and v4 = (v4, v3) in (v1, v3) Pour voir toutes les égalités (est-ce souhaitable ?), il faut changer un peu plus la structure du code de Genprintval -- Alain |
Issue History |
|||
| Date Modified | Username | Field | Change |
| 2005-11-18 10:13 | administrator | New Issue | |
| Copyright © 2000 - 2011 MantisBT Group |