Le Friday 06 Jan 2012 à 14:08:27 (-0800), DelPhiNus a écrit : > Indeed. OCaml is far safer than most of the other langage I know so I > was very surprised to find such problem and I am a bit worried now... > > I will try to make a smaller later and post a bug. > > Regards, > Delphin
I'm not so surprised at this behaviour. The function next mutates cur_name. The call to name accesses cur_name. The 'match next source, name () with' makes a call to next and to name, but you cannot know the order. There is no reason that it would evaluate in the same order as the 'let ... in' analogue. For instance, it may be possible that the 'match ... with' case evaluates in a different order than the 'let ... in' case for two reasons: [1] The evaluation order of 'match ... with' might be guided by what pattern matching there is to be done. Evaluating in one order might be more efficient than the reverse order. [2] Doing 'let ... in' forces evaluation of what's inside the let before going after what's after the 'in'. Might not be entirely true for 'match ... with'. You can try -dlambda, -S or dumping the bytecode to see what happens in each case. (-dlambda gives you the last intermediate representation before generation of asm or bytecode, -S gives you asm files). Would be nice to have some linear logic in OCaml's type system for these kind of things... > On 6 jan, 20:08, Chris King <[email protected]> wrote: > > This looks like a bug in OCaml (which is in my experience rare!), and > > an insidious one at that. > > > > I defined: > > > > let print_event = function > > | StartElement -> print_string "StartElement " > > | EndElement -> print_string "EndElement " > > | Text -> print_string "Text " > > | EndOfDocument -> print_string "EndOfDocument " > > > > and changed the failing case to: > > > > | (ev, name) as foo -> begin > > print_event (fst foo); print_endline (snd foo); > > print_event ev; print_endline name; > > print_newline (); > > if test foo then handle_next a else a > > end > > > > and look at the garbage OCaml prints out: > > > > StartElement toto > > StartElement toto > > > > StartElement titi > > EndElement titi > > > > EndOfDocument toto > > EndElement toto > > > > Exception: Failure "Unexpected end of source". > > > > (Each pair of lines should be identical.) This is in 3.11.2 on Ubuntu > > x86_64, and happens with both bytecode and compiled code. > > > > See if you can shrink down your example while maintaining this bug and > > then file a bug report:http://caml.inria.fr/mantis/my_view_page.php > > > > On Fri, Jan 6, 2012 at 11:41 AM, DelPhiNus <[email protected]> wrote: > > > Considering the sample code below that contains non-functional stuff > > > that mimics a simple XmlScanner from my company. > > > > > type event = StartElement | EndElement | Text | EndOfDocument > > > > > let cur_name = ref None > > > let name () = match !cur_name with None -> failwith "None" | Some name > > > -> name > > > let next it = > > > match !it with > > > | [] -> failwith "Unexpected end of source" > > > | hd :: tl -> it := tl; cur_name := Some (snd hd); fst hd > > > > > let read_section_while source test f a = > > > let rec handle_next a = > > > match next source, name () with > > > | EndOfDocument, _ -> failwith "Unexpected end of > > > document" > > > | Text, _ -> handle_next (f a "Text") > > > | StartElement, "titi" -> handle_next (f a "Start titi") > > > | EndElement, "tata" -> handle_next (f a "End tata") > > > | xml -> if test xml then > > > handle_next a else a > > > in > > > handle_next a > > > > > let source = [ > > > (StartElement, "toto"); > > > (StartElement, "titi"); > > > (EndElement, "titi"); > > > (StartElement, "tata"); > > > (EndElement, "tata"); > > > (EndElement, "toto"); > > > (EndOfDocument, "dummy") > > > ];; > > > > > read_section_while (ref source) ((<>) (EndElement, "toto")) (fun a x - > > >> x :: a) [];; > > > > > ==== END SAMPLE === > > > > > I have an exception "Unexpected end of source" while the code was > > > supposed to stop normally on (EndElement, "toto") > > > > > The same code works as expected if I just change slightly the default > > > pattern: > > > | ev, name -> if test (ev, name) then handle_next a else a > > > instead of: > > > | xml -> if test xml then handle_next a else a > > > > > Again, the same code works if I make the tuple resulting from (next > > > it, name ()) just before the pattern matching: > > > let x = next source, name () in match next x with > > > instead of: > > > match next source, name () with > > > > > From my point of view, I thought that there was no fundamental > > > difference between the code that works and the code that fails. Maybe > > > I missed something... > > > > > I am using Ocaml 3.11.0 and I don't plan to update for the moment > > > since I am experiencing 3rd party library link problems as soon as > > > something change in the Ocaml+MinGW+Cygwin+FlexDLL toolchain. -- Guillaume Yziquel http://yziquel.homelinux.org -- You received this message because you are subscribed to the Google Groups "ocaml-developer" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/ocaml-developer?hl=en For other OCaml forums, see http://caml.inria.fr/resources/forums.en.html
