| Anonymous | Login | Signup for a new account | 2013-06-20 14:42 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 | |||||||
| 0001248 | OCaml | OCaml general | public | 2002-07-18 20:23 | 2012-01-25 15:01 | |||||||
| Reporter | administrator | |||||||||||
| Assigned To | ||||||||||||
| Priority | normal | Severity | feature | Reproducibility | always | |||||||
| Status | resolved | Resolution | suspended | |||||||||
| Platform | OS | OS Version | ||||||||||
| Product Version | ||||||||||||
| Target Version | Fixed in Version | |||||||||||
| Summary | 0001248: Generation d'exceptions | |||||||||||
| Description | Suite à un thread sur comp.lang.ml (cf <ah6vmf$12ik$1@nef.ens.fr>) ... La session suivante illustre quelques problèmes avec la génération d'exception lors de l'évaluation de structures: # module F(X:sig type t end) = struct exception E of X.t end;; module F : functor (X : sig type t end) -> sig exception E of X.t end # module B = F(struct type t = bool end);; module B : sig exception E of bool end # B.E true;; - : exn = F(X).E 1 Le toplevel croit faussement que l'argument de B.E est de type int .... Le X dans l'affichage est surprenant. De même: # module X = struct type t = A | B end;; module X : sig type t = A | B end # module FX = F(X);; module FX : sig exception E of X.t end # FX.E X.A;; - : exn = F(X).E 0 Enfin, ça ne serait qu'un problème d'affichage. Mais ce qui suit est plus troublant: # FX.E X.B = B.E true;; - : bool = true Donc OCaml compare des valeurs de type différent, et répond même "true" ! On s'attend à ce que les exceptions aient un comportement génératif; mais non: # let f () = let module E = struct exception E end in E.E;; val f : unit -> exn = <fun> # f () = f ();; - : bool = true Je dirais que cette réponse est incorrecte (en tout cas, incohérente avec le filtrage dans un gestionnaire d'exception, qui distinguerait bien ces deux exceptions). Tout ça avec OCaml 3.04 et 3.04+15 (2002-06-18). -- Alain | |||||||||||
| Tags | No tags attached. | |||||||||||
| Attached Files | ||||||||||||
Relationships |
||||||
|
||||||
Notes |
|
|
(0000133) administrator (administrator) 2002-07-19 10:27 |
Bonjour Alain, > Suite à un thread sur comp.lang.ml (cf <ah6vmf$12ik$1@nef.ens.fr>) ... > > La session suivante illustre quelques problèmes avec la génération > d'exception lors de l'évaluation de structures: > > # module F(X:sig type t end) = struct exception E of X.t end;; > module F : functor (X : sig type t end) -> sig exception E of X.t end > # module B = F(struct type t = bool end);; > module B : sig exception E of bool end > # B.E true;; > - : exn = F(X).E 1 > > Le toplevel croit faussement que l'argument de B.E est de type int .... > Le X dans l'affichage est surprenant. > > De même: > > # module X = struct type t = A | B end;; > module X : sig type t = A | B end > # module FX = F(X);; > module FX : sig exception E of X.t end > # FX.E X.A;; > - : exn = F(X).E 0 > > Enfin, ça ne serait qu'un problème d'affichage. C'est en effet un problème d'affichage. L'identité d'une référence est représentée par une référence vers une chaîne de caractère. L'égalité physique entre ces références est ce qui définit la "générativité" des exceptions, et sert à implémenter le filtrage sur les exceptions. Malheureusement, l'adresse d'une référence, c'est pas terrible pour l'affichage. Le compilateur essaye de mettre dans la chaîne de caractère des infos utiles pour imprimer l'exception, en l'occurrence un chemin d'accès à la définition de la référence: exception E of int ---> "E" module X = struct exception E of bool end ---> "X.E" ton foncteur ci-dessus ---> "F(X).E" Bien sûr, le cas du foncteur n'est pas très intéressant car une fois le foncteur appliqué, l'argument ne s'appellera pas X. Mais le but est juste d'aider l'utilisateur à localiser la définition de l'exception lorsque il se prend un message "Uncaught exception". On pourrait mettre "F().E" à la place, ou "F.E", ou... Maintenant, quid de l'affichage d'une valeur de type "exn" au toplevel. Le gros problème est de retrouver le type de l'argument éventuel de l'exception. C'est en général impossible, car on peut être entièrement sorti du "scope" de la définition de l'exception. Cependant, le toplevel fait un "best effort" (le brave garçon): il essaye de résoudre le chemin trouvé dans le nom de l'exception et regarde s'il s'évalue en le même identifiant d'exception (la même référence) que celui trouvé dans la valeur d'exception. Si oui, c'est gagné, on a retrouvé le type de l'argument et on peut afficher correctement. Si non, on fait un deuxième "best effort" qui consiste à afficher la valeur de l'argument sans infos de types statiques, juste en s'appuyant sur les tags runtime. Ça marche bien pour les chaînes de caractères, et très mal pour les entiers/booléens/constructeurs constants, comme ton exemple le montre... Je vois que ces "best efforts" entraînent une certaine confusion chez des utilisateurs rigoureux dans ton genre :-) Je veux bien en enlever, ça supprimera du code pas très joli dans le toplevel, mais attention à ne pas sacrifier sur l'autel de la pureté idéologique tous les hints qui pourraient aider l'utilisateur à comprendre d'où vient cette fichue exception non rattrapée. > Mais ce qui suit est plus troublant: > > # FX.E X.B = B.E true;; > - : bool = true > > Donc OCaml compare des valeurs de type différent, et répond même "true" ! C'est un glitch de plus dans l'égalité générique: les "string ref" qui encodent l'identité des exceptions sont comparées par contenu et non par adresse... C'est très gênant en effet car si ces string ref ne sont pas ==, les restes des blocs exception ne sont pas forcément du même type et ne devraient pas être comparés... > On s'attend à ce que les exceptions aient un comportement > génératif; mais non: Pas d'accord: le filtrage sur les exceptions (match ou try...with) implémente exactement le comportement génératif attendu. Refais tes tests proprement avec des "match" et tout ira bien. - Xavier |
|
(0000134) administrator (administrator) 2002-07-20 11:29 |
On Fri, 19 Jul 2002, Xavier Leroy wrote: > C'est en effet un problème d'affichage. L'identité d'une référence > est représentée par une référence vers une chaîne de caractère. > L'égalité physique entre ces références est ce qui définit la > "générativité" des exceptions, et sert à implémenter le filtrage sur > les exceptions. C'est un peu surprenant, car le filtrage correspond plutôt à une égalité (=), mais ce n'est pas bien grave. > Je vois que ces "best efforts" entraînent une certaine confusion chez > des utilisateurs rigoureux dans ton genre :-) Je veux bien en > enlever, ça supprimera du code pas très joli dans le toplevel, mais > attention à ne pas sacrifier sur l'autel de la pureté idéologique tous > les hints qui pourraient aider l'utilisateur à comprendre d'où vient > cette fichue exception non rattrapée. Oui, ça se défend ... > > Mais ce qui suit est plus troublant: > > > > # FX.E X.B = B.E true;; > > - : bool = true > > > > Donc OCaml compare des valeurs de type différent, et répond même "true" ! > > C'est un glitch de plus dans l'égalité générique: les "string ref" qui > encodent l'identité des exceptions sont comparées par contenu et non > par adresse... C'est très gênant en effet car si ces string ref ne > sont pas ==, les restes des blocs exception ne sont pas forcément du > même type et ne devraient pas être comparés... Il serait possible d'imposer pour les exceptions que ces strings ref soient bien == pour avoir égalité (soit avec un tag runtime spécifique pour les exceptions, soit en utilisant une valeur particulière x [allouée une fois pour toute] et en codant les identités par un couple (x,nom); lorsque la comparaison générique rencontre x dans un bloc, elle passe en mode "égalité physique"). Je ne sais pas si ça en vaut la peine, bien sûr. > > On s'attend à ce que les exceptions aient un comportement > > génératif; mais non: > > Pas d'accord: le filtrage sur les exceptions (match ou try...with) > implémente exactement le comportement génératif attendu. Refais tes > tests proprement avec des "match" et tout ira bien. Ok, mais on ne peut pas toujours utiliser le filtrage, par exemple si l'exception à rattraper n'est pas connue statiquement. Bon, c'est un peu tiré par les cheveux, mais: let expect_exn exn f x = try f x; false with e when e = exn -> true ne fait pas ce que l'on veut (ce genre de fonction pourrait être utilisé pour faire des tests de regression, par exemple). -- Alain |
|
(0006794) doligez (manager) 2012-01-25 15:00 |
Allocating a runtime tag just for this problem: out of question. Adding a special case for comparison: I don't think the problem is big enough to warrant such a solution. Another possibility would be to wrap the exception string in an object because objects are never compared structurally. But how much existing C code would be broken by that change? I'm setting this to resolved/suspended (waiting for someone to come up with a good solution and a patch). |
Issue History |
|||
| Date Modified | Username | Field | Change |
| 2005-11-18 10:13 | administrator | New Issue | |
| 2008-04-10 14:51 | doligez | Relationship added | related to 0004531 |
| 2012-01-25 15:00 | doligez | Note Added: 0006794 | |
| 2012-01-25 15:00 | doligez | Status | acknowledged => resolved |
| 2012-01-25 15:00 | doligez | Resolution | open => suspended |
| 2012-01-25 15:00 | doligez | Description Updated | View Revisions |
| 2012-01-25 15:01 | doligez | Relationship replaced | has duplicate 0004531 |
| Copyright © 2000 - 2011 MantisBT Group |