* [Caml-list] kprintf with user formatters @ 2004-06-30 16:32 Damien 2004-07-14 21:10 ` Pierre Weis 0 siblings, 1 reply; 56+ messages in thread From: Damien @ 2004-06-30 16:32 UTC (permalink / raw) To: Ocaml Hi, I am writing a multi-threaded program, so that I need some synchronization when pretty-printing things : << #directory "+threads";; #load "unix.cma";; #load "threads.cma";; module Debug = struct let m = Mutex.create() let printf x = Format.kprintf (fun s -> Mutex.lock m; print_endline s; Mutex.unlock m) x end;; (* module Debug : sig val m: Mutex.t val printf : ('a, unit, string, unit) format4 -> 'a end *) >> but now, I can't _nicely_ use my previously defined printers : suppose I have got a type with its toplevel pretty-printer : << type t val format_t: Format.formatter -> t -> unit val x: t >> I would like to write : << Debug.printf "val t = %a" format_t x >> but I cannot since the user printer is expected to be "unit->t->string" (while it is "formatter->t->unit" for the standard Format.printf "%a") currently I use : << let (!!) f = (fun () x -> f Format.str_formatter x; Format.flush_str_formatter());; (* val (!!): (Format.formatter -> 'a -> 'b) -> unit -> 'a -> string *) Debug.printf "val t = %a" !!format_t x >> this seems to be working, but I wonder if : - there is a better solution - this use of the global value "Format.str_formatter" is really thread-safe (I would say no...) - I missed something - printf could not understand a conversion character 'A' that would always need a _general_ user-formatter (of type formatter->t->unit) thanks, damien ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-06-30 16:32 [Caml-list] kprintf with user formatters Damien @ 2004-07-14 21:10 ` Pierre Weis 2004-07-15 0:17 ` Markus Mottl 0 siblings, 1 reply; 56+ messages in thread From: Pierre Weis @ 2004-07-14 21:10 UTC (permalink / raw) To: Damien; +Cc: caml-list Hi, > I am writing a multi-threaded program, so that I need some > synchronization when pretty-printing things : [...] > module Debug = struct > let m = Mutex.create() > let printf x = > Format.kprintf > (fun s -> Mutex.lock m; print_endline s; Mutex.unlock m) > x > end;; > (* > module Debug : sig > val m: Mutex.t > val printf : ('a, unit, string, unit) format4 -> 'a > end > *) > > but now, I can't _nicely_ use my previously defined printers : > type t > val format_t: Format.formatter -> t -> unit > val x: t > > I would like to write : > << > Debug.printf "val t = %a" format_t x > >> > > but I cannot since the user printer is expected to be "unit->t->string" > (while it is "formatter->t->unit" for the standard Format.printf "%a") Your problem is thus that the function Debug.printf is not the right one (since it has not the right type :) Hence, you should use another definition for Debug.printf let printf fmt = Format.kfprintf (fun ppf -> ()) Format.err_formatter fmt This way, you get: printf "%a";; - : (Format.formatter -> '_a -> unit) -> '_a -> unit = <fun> as expected. However, your problem is simpler than that: you just have to define a custom formatter devoted to your debugging purposes. For instance: module Debug = struct let m = Mutex.create () let out s idx len = Mutex.lock m; prerr_string (String.sub s idx len); flush stderr; Mutex.unlock m let flush () = flush stderr let dppf = Format.make_formatter out flush let printf fmt = Format.fprintf dppf fmt end;; Now you can substitute Debug.printf to any well-typed occurrence of Format.printf, since we have: # Debug.printf;; - : ('a, Format.formatter, unit) format -> 'a = <fun> # Format.printf;; - : ('a, Format.formatter, unit) format -> 'a = <fun> > currently I use : > > let (!!) f = (fun () x -> > f Format.str_formatter x; > Format.flush_str_formatter());; > (* val (!!): (Format.formatter -> 'a -> 'b) -> unit -> 'a -> string *) > > Debug.printf "val t = %a" !!format_t x > > this seems to be working, but I wonder if : > - there is a better solution See above: a custom formatter is probably simpler and more elegant. > - this use of the global value "Format.str_formatter" is really > thread-safe (I would say no...) I'm afraid I could not answer for sure to this one: let's say that using Format.str_formatter is as thread safe as using a Buffer.t value and the Buffer.add_* functions. Also, can we consider in the first place that using any printf variant could be thread safe ? If the answer is no, you would need to stick to pp_* versions of the basic primitives and this would be a major modification of your code. > - I missed something May be you missed the fact that Format was designed from the beginning to support formatting in parallel to user's defined pretty-printing engines. > - printf could not understand a conversion character 'A' that would > always need a _general_ user-formatter (of type formatter->t->unit) Once more, I cannot answer to this question: I need some time to figure out what it mean in term of typing (and semantics of printf)... Tell me if the suggested solution solves your problem. Best regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-14 21:10 ` Pierre Weis @ 2004-07-15 0:17 ` Markus Mottl 2004-07-15 7:30 ` David MENTRE ` (3 more replies) 0 siblings, 4 replies; 56+ messages in thread From: Markus Mottl @ 2004-07-15 0:17 UTC (permalink / raw) To: Pierre Weis; +Cc: caml-list On Wed, 14 Jul 2004, Pierre Weis wrote: > Your problem is thus that the function Debug.printf is not the right > one (since it has not the right type :) Btw., since we are at it: I'd like to use my own printers depending on a conditional, e.g.: let log level fmt = if may_log level then kfprintf ... else ??? If the given log level "level" does not allow logging the message specified by "fmt", I just want to ignore the parameters provided together with "fmt" - but how? Is there some (safe) trick, or do I have to write my own Printf/Format-modules? I don't want to waste computation time by unnecessarily converting format arguments to strings, which may be very costly, e.g. when this would mean converting IPs to hostnames, etc. Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 0:17 ` Markus Mottl @ 2004-07-15 7:30 ` David MENTRE 2004-07-15 7:59 ` Jean-Christophe Filliatre 2004-07-15 7:39 ` Damien ` (2 subsequent siblings) 3 siblings, 1 reply; 56+ messages in thread From: David MENTRE @ 2004-07-15 7:30 UTC (permalink / raw) To: caml-list Hello, Markus Mottl <markus@oefai.at> writes: > Btw., since we are at it: I'd like to use my own printers depending on > a conditional, e.g.: > > let log level fmt = > if may_log level then > kfprintf ... > else > ??? > > If the given log level "level" does not allow logging the message > specified by "fmt", I just want to ignore the parameters provided together > with "fmt" - but how? # let cur_level = ref 0;; val cur_level : int ref = {contents = 0} # let log level fmt = let print_at_level str = if !cur_level >= level then print_string str in Format.kprintf print_at_level fmt;; val log : int -> ('a, unit, string, unit) format4 -> 'a = <fun> # log 3 "%d %s" 3 "toto";; - : unit = () # cur_level := 4;; - : unit = () # log 3 "%d %s" 3 "toto";; 3 toto- : unit = () The trick is to call kprintf as last expression. Thank you to Damien Doligez: http://caml.inria.fr/archives/200405/msg00355.html I hope it helps, Yours, d. -- David Mentré <dmentre@linux-france.org> ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 7:30 ` David MENTRE @ 2004-07-15 7:59 ` Jean-Christophe Filliatre 2004-07-15 23:35 ` henri dubois-ferriere 0 siblings, 1 reply; 56+ messages in thread From: Jean-Christophe Filliatre @ 2004-07-15 7:59 UTC (permalink / raw) To: David MENTRE; +Cc: caml-list David MENTRE writes: > > > If the given log level "level" does not allow logging the message > > specified by "fmt", I just want to ignore the parameters provided together > > with "fmt" - but how? > > # let cur_level = ref 0;; > val cur_level : int ref = {contents = 0} > # let log level fmt = > let print_at_level str = if !cur_level >= level then print_string str in > Format.kprintf print_at_level fmt;; > val log : int -> ('a, unit, string, unit) format4 -> 'a = <fun> This solution still has the drawback of evaluating the whole message (which can be costly). Damien Pous's post has the expected behavior (printf arguments are simply discarded without any evaluation) but requires Obj.magic... -- Jean-Christophe ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 7:59 ` Jean-Christophe Filliatre @ 2004-07-15 23:35 ` henri dubois-ferriere 0 siblings, 0 replies; 56+ messages in thread From: henri dubois-ferriere @ 2004-07-15 23:35 UTC (permalink / raw) To: Jean-Christophe Filliatre; +Cc: David MENTRE, caml-list any idea how this would compare (performance-wise) to building a closure (fun () -> printf ...) , and then evaluating the closure only when the debug level is ok? henri On Thu, 15 Jul 2004 09:59:45 +0200, Jean-Christophe Filliatre <jean-christophe.filliatre@lri.fr> wrote: > > David MENTRE writes: > > > > > If the given log level "level" does not allow logging the message > > > specified by "fmt", I just want to ignore the parameters provided together > > > with "fmt" - but how? > > > > # let cur_level = ref 0;; > > val cur_level : int ref = {contents = 0} > > # let log level fmt = > > let print_at_level str = if !cur_level >= level then print_string str in > > Format.kprintf print_at_level fmt;; > > val log : int -> ('a, unit, string, unit) format4 -> 'a = <fun> > > This solution still has the drawback of evaluating the whole message > (which can be costly). > > Damien Pous's post has the expected behavior (printf arguments are > simply discarded without any evaluation) but requires Obj.magic... > > -- > Jean-Christophe > > > > ------------------- > To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr > Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 0:17 ` Markus Mottl 2004-07-15 7:30 ` David MENTRE @ 2004-07-15 7:39 ` Damien 2004-07-15 12:19 ` Markus Mottl 2004-07-16 6:02 ` Pierre Weis 2004-07-15 22:20 ` Pierre Weis 2004-07-16 16:17 ` james woodyatt 3 siblings, 2 replies; 56+ messages in thread From: Damien @ 2004-07-15 7:39 UTC (permalink / raw) To: caml-list On Thu, 15 Jul 2004 02:17:58 +0200 Markus Mottl wrote: > Btw., since we are at it: I'd like to use my own printers depending on > a conditional, e.g.: > > let log level fmt = > if may_log level then > kfprintf ... > else > ??? > > If the given log level "level" does not allow logging the message > specified by "fmt", I just want to ignore the parameters provided > together with "fmt" - but how? Is there some (safe) trick, or do I > have to write my own Printf/Format-modules? I don't want to waste > computation time by unnecessarily converting format arguments to > strings, which may be very costly, e.g. when this would mean > converting IPs to hostnames, etc. I had the same problem a month ago, I ended with the following ugly function: let log b fmt = if b then Printf.printf fmt else let rec f x = Obj.magic f in f fmt (* val f: bool -> ('a, out_channel, unit) format -> 'a *) (I think this is safe since f just eats its arguments, and gets typed with "-rectypes" : ('b->'a) as 'a) maybe a function "zprintf" could be added to Printf and Format to do this job ? regards, damien ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 7:39 ` Damien @ 2004-07-15 12:19 ` Markus Mottl 2004-07-15 12:42 ` Basile Starynkevitch [local] 2004-07-16 6:02 ` Pierre Weis 1 sibling, 1 reply; 56+ messages in thread From: Markus Mottl @ 2004-07-15 12:19 UTC (permalink / raw) To: Damien; +Cc: caml-bugs, OCaml On Thu, 15 Jul 2004, Damien wrote: > I had the same problem a month ago, > I ended with the following ugly function: > > let log b fmt = > if b then Printf.printf fmt > else > let rec f x = Obj.magic f in > f fmt > (* val f: bool -> ('a, out_channel, unit) format -> 'a *) > > (I think this is safe since f just eats its arguments, > and gets typed with "-rectypes" : ('b->'a) as 'a) > > maybe a function "zprintf" could be added to Printf and Format to do > this job ? Thanks for the hint, this works for me! I also think that there should be some kind of "zprintf"-function in the standard library. Forcing people to use "-rectypes" or "Obj.magic" is evil. Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 12:19 ` Markus Mottl @ 2004-07-15 12:42 ` Basile Starynkevitch [local] 2004-07-15 13:45 ` Markus Mottl 0 siblings, 1 reply; 56+ messages in thread From: Basile Starynkevitch [local] @ 2004-07-15 12:42 UTC (permalink / raw) To: caml-list On Thu, Jul 15, 2004 at 02:19:47PM +0200, Markus Mottl wrote: > On Thu, 15 Jul 2004, Damien wrote: > > I had the same problem a month ago, > > I ended with the following ugly function: > > > > let log b fmt = > > if b then Printf.printf fmt > > else > > let rec f x = Obj.magic f in > > f fmt > > (* val f: bool -> ('a, out_channel, unit) format -> 'a *) > > > > (I think this is safe since f just eats its arguments, > > and gets typed with "-rectypes" : ('b->'a) as 'a) > > > > maybe a function "zprintf" could be added to Printf and Format to do > > this job ? I don't understand what this zprintf function should be, but the above log proposal behave strangely (and perhaps unsafely) : # log false "a=%d s=%S\n%!" 1 "xyz";; - : unit = <unknown constructor> For what it's worth, long time ago, I ended writing a camlp4 extension for a similar logging (or tracing purpose) see file README.trace and pa_trace.ml of http://cvs.sourceforge.net/viewcvs.py/poesia/PoesiaSoft/PoesiaMonIcap/ Regards. -- Basile STARYNKEVITCH -- basile dot starynkevitch at inria dot fr Project cristal.inria.fr - phone +33 1 3963 5197 - mobile 6 8501 2359 http://cristal.inria.fr/~starynke --- all opinions are only mine ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 12:42 ` Basile Starynkevitch [local] @ 2004-07-15 13:45 ` Markus Mottl 2004-07-15 14:22 ` Basile Starynkevitch [local] 2004-07-16 6:17 ` [Caml-list] kprintf with user formatters Pierre Weis 0 siblings, 2 replies; 56+ messages in thread From: Markus Mottl @ 2004-07-15 13:45 UTC (permalink / raw) To: Basile Starynkevitch [local]; +Cc: caml-list On Thu, 15 Jul 2004, Basile Starynkevitch [local] wrote: > I don't understand what this zprintf function should be, It should parse the format string, and ignore format arguments following it. > but the above > log proposal behave strangely (and perhaps unsafely) : > > # log false "a=%d s=%S\n%!" 1 "xyz";; > - : unit = <unknown constructor> The reason for this is that it returns a function and not a unit value. Unless you parse the format string, there is no way you can know when to stop eating arguments to return a value. I don't think that this hack will be too dangerous. You might get an exception 'Invalid_argument "equal: functional value"' if you want to compare those fancy unit-values, which is about the worst thing you can achieve. But who would want to compare unit-values anyway? > For what it's worth, long time ago, I ended writing a camlp4 extension > for a similar logging (or tracing purpose) see file README.trace and > pa_trace.ml of > http://cvs.sourceforge.net/viewcvs.py/poesia/PoesiaSoft/PoesiaMonIcap/ The preprocessor is not good enough for me. I would like to change log levels at runtime, because the application is a server which should run permanently. Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 13:45 ` Markus Mottl @ 2004-07-15 14:22 ` Basile Starynkevitch [local] 2004-07-15 14:57 ` Markus Mottl 2004-07-16 6:47 ` Pierre Weis 2004-07-16 6:17 ` [Caml-list] kprintf with user formatters Pierre Weis 1 sibling, 2 replies; 56+ messages in thread From: Basile Starynkevitch [local] @ 2004-07-15 14:22 UTC (permalink / raw) To: caml-list On Thu, Jul 15, 2004 at 03:45:30PM +0200, Markus Mottl wrote: > On Thu, 15 Jul 2004, Basile Starynkevitch [local] wrote: > > I don't understand what this zprintf function should be, > > It should parse the format string, and ignore format arguments following > it. let zprintf fmt = Printf.kprintf (fun _ -> ()) fmt should be ok. But I think that the format string should not even be parsed. I've got no solution (except the one below) to this! > > I don't think that this hack will be too dangerous. You might get an > exception 'Invalid_argument "equal: functional value"' if you want to > compare those fancy unit-values, which is about the worst thing you > can achieve. But who would want to compare unit-values anyway? > > > For what it's worth, long time ago, I ended writing a camlp4 extension > > for a similar logging (or tracing purpose) see file README.trace and > > pa_trace.ml of > > http://cvs.sourceforge.net/viewcvs.py/poesia/PoesiaSoft/PoesiaMonIcap/ > > The preprocessor is not good enough for me. I would like to change > log levels at runtime, because the application is a server which should > run permanently. The above hack was written with the same requirements, and provide the possibility to change log levels (or log flags actually). Actually, I more and more hate printf, both in C and in Ocaml. I really believe it is a nightmare. A possible suggestion might be to add a StopPrintf exception to Printf and add a tryprintf function to Printf, which takes a prologue function as an argument. If the prologue raises an exception, no formatting occur; otherwise, tryprintf works like kprintf -- Basile STARYNKEVITCH -- basile dot starynkevitch at inria dot fr Project cristal.inria.fr - phone +33 1 3963 5197 - mobile 6 8501 2359 http://cristal.inria.fr/~starynke --- all opinions are only mine ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 14:22 ` Basile Starynkevitch [local] @ 2004-07-15 14:57 ` Markus Mottl 2004-07-16 6:47 ` Pierre Weis 1 sibling, 0 replies; 56+ messages in thread From: Markus Mottl @ 2004-07-15 14:57 UTC (permalink / raw) To: Basile Starynkevitch [local]; +Cc: caml-list On Thu, 15 Jul 2004, Basile Starynkevitch [local] wrote: > let zprintf fmt = Printf.kprintf (fun _ -> ()) fmt > should be ok. This would force string conversion of arguments, which is what I want to avoid, because some of those computations (user-defined ones) would just be too costly. > But I think that the format string should not even be parsed. I've got > no solution (except the one below) to this! It has to be if you want to avoid those computations and return a meaningful value. But the recursive argument-eating function is ok for me, too. > The above hack was written with the same requirements, and provide the > possibility to change log levels (or log flags actually). Ok, I see. This is certainly a way to do it, though it requires the preprocessor. It would still be nice to have an efficient, clean solution without resorting to additional tools. Thanks, anyway! Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 14:22 ` Basile Starynkevitch [local] 2004-07-15 14:57 ` Markus Mottl @ 2004-07-16 6:47 ` Pierre Weis 2004-07-16 7:13 ` Jean-Christophe Filliatre ` (2 more replies) 1 sibling, 3 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-16 6:47 UTC (permalink / raw) To: Basile Starynkevitch [local]; +Cc: caml-list > On Thu, Jul 15, 2004 at 03:45:30PM +0200, Markus Mottl wrote: > > On Thu, 15 Jul 2004, Basile Starynkevitch [local] wrote: > > > I don't understand what this zprintf function should be, > > > > It should parse the format string, and ignore format arguments following > > it. > > let zprintf fmt = Printf.kprintf (fun _ -> ()) fmt > should be ok. > > But I think that the format string should not even be parsed. I've got > no solution (except the one below) to this! Well, you just need to think functionnally! If I understand properly: - you want to skip the runtime time penalty of formatting the arguments to string before discarding the result, - you even want not to parse the format string, - ideally you also want NOT TO EVALUATE the reminding arguments of your printf call ? Hmm, this sounds extremely lazy to me; so this suggests thunk programming; hey, we have that in the language, so let's go! let log level thunk = if may_log level then thunk ();; ... log 2 (fun () -> eprintf "Argument 1 is hard to compute %d\n" (ackermann x x)) That's the way we use to log in the OcamlP3l compiler: we've got no runtime penalty if there is no necessity to log. Moreover, this solution is general enough to accomodate threads, side effects, or whatever. To me the (fun () -> ) additional verbosity is not so bad: it clearly emphasizes that nothing at all is evaluated when logging is unnecessary. To go beyond that, we would need some help from the language that would offer some provision for debugging from a special debug keyword, semantically reminiscent to lazy and assert (as a kind of combined semantics of both constructs). A compiler flag would then automatically remove the debugging code (as is done for assert with the -noassert flag) and the compiler will automatically insert the (fun () -> ) as it already does in the case of lazy ... [...] > Actually, I more and more hate printf, both in C and in Ocaml. I > really believe it is a nightmare. Could you elaborate a bit ? We worked hard to provide a clean fully typed interface to printf and, well ... we like using it :) We may have missed the point that makes your printf experience ``a nightmare'', and having information on that could be helpful to improve the implementation. > A possible suggestion might be to > add a StopPrintf exception to Printf > and > add a tryprintf function to Printf, which takes a prologue function > as an argument. If the prologue raises an exception, no formatting > occur; otherwise, tryprintf works like kprintf I don't think the problem is in printf. The problem is in the way you call printf (no printf variant could prevent evaluating the format string and evaluating the arguments of its call: this is mandatory due to the semantics of the language). Best regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 6:47 ` Pierre Weis @ 2004-07-16 7:13 ` Jean-Christophe Filliatre 2004-07-16 7:23 ` henri dubois-ferriere ` (2 more replies) 2004-07-16 7:21 ` henri dubois-ferriere 2004-07-16 17:44 ` Markus Mottl 2 siblings, 3 replies; 56+ messages in thread From: Jean-Christophe Filliatre @ 2004-07-16 7:13 UTC (permalink / raw) To: Pierre Weis; +Cc: Basile Starynkevitch [local], caml-list Pierre Weis writes: > > If I understand properly: > > - you want to skip the runtime time penalty of formatting the > arguments to string before discarding the result, > - you even want not to parse the format string, > - ideally you also want NOT TO EVALUATE the reminding arguments of > your printf call ? > > Hmm, this sounds extremely lazy to me; so this suggests thunk > programming; hey, we have that in the language, so let's go! > > let log level thunk = > if may_log level then thunk ();; > > ... > > log 2 (fun () -> > eprintf "Argument 1 is hard to compute %d\n" (ackermann x x)) I also use the same kind of trick in practice, with a little refinement to avoid building the closure. I introduce higher-order functions such as val if_debug : ('a -> unit) -> 'a -> unit which behaves like application when the debug flag is on (and does nothing otherwise). Then you can simply write ... if_debug eprintf "this is a message"; ... I even introduce variants for functions with more than one argument to be able to write stuff like ... if_debug3 eprintf "syntax tree is %a@." print_tree t; ... without addition of parentheses. I still find this very convenient and not obtrusive as far as style is concerned. Hope this helps, -- Jean-Christophe Filliâtre (http://www.lri.fr/~filliatr) ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 7:13 ` Jean-Christophe Filliatre @ 2004-07-16 7:23 ` henri dubois-ferriere 2004-07-16 7:44 ` Jean-Christophe Filliatre 2004-07-16 17:56 ` Markus Mottl 2004-07-19 9:17 ` Pierre Weis 2 siblings, 1 reply; 56+ messages in thread From: henri dubois-ferriere @ 2004-07-16 7:23 UTC (permalink / raw) To: Jean-Christophe Filliatre Cc: Pierre Weis, Basile Starynkevitch [local], caml-list this sounds interesting! could you point us to any available code showing more of this in practice? thanks henri On Fri, 16 Jul 2004 09:13:20 +0200, Jean-Christophe Filliatre <jean-christophe.filliatre@lri.fr> wrote: > > Pierre Weis writes: > > > > If I understand properly: > > > > - you want to skip the runtime time penalty of formatting the > > arguments to string before discarding the result, > > - you even want not to parse the format string, > > - ideally you also want NOT TO EVALUATE the reminding arguments of > > your printf call ? > > > > Hmm, this sounds extremely lazy to me; so this suggests thunk > > programming; hey, we have that in the language, so let's go! > > > > let log level thunk = > > if may_log level then thunk ();; > > > > ... > > > > log 2 (fun () -> > > eprintf "Argument 1 is hard to compute %d\n" (ackermann x x)) > > I also use the same kind of trick in practice, with a little > refinement to avoid building the closure. I introduce higher-order > functions such as > > val if_debug : ('a -> unit) -> 'a -> unit > > which behaves like application when the debug flag is on (and does > nothing otherwise). Then you can simply write > > ... > if_debug eprintf "this is a message"; > ... > > I even introduce variants for functions with more than one argument to > be able to write stuff like > > ... > if_debug3 eprintf "syntax tree is %a@." print_tree t; > ... > > without addition of parentheses. I still find this very convenient and > not obtrusive as far as style is concerned. > > Hope this helps, > -- > Jean-Christophe Filliâtre (http://www.lri.fr/~filliatr) > > > > ------------------- > To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr > Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 7:23 ` henri dubois-ferriere @ 2004-07-16 7:44 ` Jean-Christophe Filliatre 0 siblings, 0 replies; 56+ messages in thread From: Jean-Christophe Filliatre @ 2004-07-16 7:44 UTC (permalink / raw) To: henri dubois-ferriere Cc: Pierre Weis, Basile Starynkevitch [local], caml-list henri dubois-ferriere writes: > this sounds interesting! could you point us to any available code > showing more of this in practice? Sure: http://why.lri.fr/ (this is a software verification tool) You'll find many instances of the trick I was describing in src/main.ml -- Jean-Christophe Filliâtre henri dubois-ferriere writes: > On Fri, 16 Jul 2004 09:13:20 +0200, Jean-Christophe Filliatre > <jean-christophe.filliatre@lri.fr> wrote: > > > > Pierre Weis writes: > > > > > > If I understand properly: > > > > > > - you want to skip the runtime time penalty of formatting the > > > arguments to string before discarding the result, > > > - you even want not to parse the format string, > > > - ideally you also want NOT TO EVALUATE the reminding arguments of > > > your printf call ? > > > > > > Hmm, this sounds extremely lazy to me; so this suggests thunk > > > programming; hey, we have that in the language, so let's go! > > > > > > let log level thunk = > > > if may_log level then thunk ();; > > > > > > ... > > > > > > log 2 (fun () -> > > > eprintf "Argument 1 is hard to compute %d\n" (ackermann x x)) > > > > I also use the same kind of trick in practice, with a little > > refinement to avoid building the closure. I introduce higher-order > > functions such as > > > > val if_debug : ('a -> unit) -> 'a -> unit > > > > which behaves like application when the debug flag is on (and does > > nothing otherwise). Then you can simply write > > > > ... > > if_debug eprintf "this is a message"; > > ... > > > > I even introduce variants for functions with more than one argument to > > be able to write stuff like > > > > ... > > if_debug3 eprintf "syntax tree is %a@." print_tree t; > > ... > > > > without addition of parentheses. I still find this very convenient and > > not obtrusive as far as style is concerned. > > > > Hope this helps, > > -- > > Jean-Christophe Filliâtre (http://www.lri.fr/~filliatr) > > > > > > > > ------------------- > > To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr > > Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ > > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > > ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 7:13 ` Jean-Christophe Filliatre 2004-07-16 7:23 ` henri dubois-ferriere @ 2004-07-16 17:56 ` Markus Mottl 2004-07-19 9:17 ` Pierre Weis 2 siblings, 0 replies; 56+ messages in thread From: Markus Mottl @ 2004-07-16 17:56 UTC (permalink / raw) To: OCaml On Fri, 16 Jul 2004, Jean-Christophe Filliatre wrote: > I also use the same kind of trick in practice, with a little > refinement to avoid building the closure. I introduce higher-order > functions such as > > val if_debug : ('a -> unit) -> 'a -> unit This actually looks quite nice to me! Though one needs to add several functions for varying numbers of arguments, this makes hardly any difference syntactically, and it is still sufficiently easy to maintain. On Fri, 16 Jul 2004, Damien wrote: > > It is overkill to introduce a new printf function just for that case. > maybe... > but it is not to hard to implement (after a quick look at printf.ml) > without the "invalid unit value" problem: Yes, a change like this in the Printf/Format-implementation was what I was thinking about. Just count the number of arguments in the format and discard them. This is sufficiently efficient (no allocations) and convenient. Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 7:13 ` Jean-Christophe Filliatre 2004-07-16 7:23 ` henri dubois-ferriere 2004-07-16 17:56 ` Markus Mottl @ 2004-07-19 9:17 ` Pierre Weis 2004-07-19 9:32 ` Jean-Christophe Filliatre 2 siblings, 1 reply; 56+ messages in thread From: Pierre Weis @ 2004-07-19 9:17 UTC (permalink / raw) To: Jean-Christophe.Filliatre; +Cc: pierre.weis, basile.starynkevitch, caml-list [...] > I also use the same kind of trick in practice, with a little > refinement to avoid building the closure. I introduce higher-order > functions such as > > val if_debug : ('a -> unit) -> 'a -> unit > > which behaves like application when the debug flag is on (and does > nothing otherwise). Then you can simply write [...] This does not solve the problem of evaluating the argument(s) of the logging application. Consider the example I gave: > log 2 (fun () -> > eprintf "Argument 1 is hard to compute %d\n" (ackermann x x)) Your solution would lead to if_debug2 eprintf "Argument 1 is hard to compute %d\n" (ackermann x x) which wastes is too much computing power when the debug turn out to be off. This is not purely rethorical: I already encountered this problem in practice (the runtime with logging output turned to off was still so slow that it was impossible to compute the result in a comfortable time delay; I was obliged to turn the logging facility to the (fun () -> ...) style to continue the development). The solution is the same as for the previous request (``not converting the arguments to strings before discarding the result''): use a devoted construct that would change the semantics for this common but arguably very specific case. Regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-19 9:17 ` Pierre Weis @ 2004-07-19 9:32 ` Jean-Christophe Filliatre 0 siblings, 0 replies; 56+ messages in thread From: Jean-Christophe Filliatre @ 2004-07-19 9:32 UTC (permalink / raw) To: Pierre Weis; +Cc: basile.starynkevitch, caml-list Pierre Weis writes: > > This does not solve the problem of evaluating the argument(s) of the logging > application. Consider the example I gave: > > > log 2 (fun () -> > > eprintf "Argument 1 is hard to compute %d\n" (ackermann x x)) > > Your solution would lead to > > if_debug2 eprintf "Argument 1 is hard to compute %d\n" (ackermann x x) > > which wastes is too much computing power when the debug turn out to be > off. This is indeed right, in the general case. However the way I use it, all the computation is always within a function being the first argument of a printf %a, and thus not evaluated (as in the print_tree example I gave). -- Jean-Christophe ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 6:47 ` Pierre Weis 2004-07-16 7:13 ` Jean-Christophe Filliatre @ 2004-07-16 7:21 ` henri dubois-ferriere 2004-07-16 17:44 ` Markus Mottl 2 siblings, 0 replies; 56+ messages in thread From: henri dubois-ferriere @ 2004-07-16 7:21 UTC (permalink / raw) To: Pierre Weis; +Cc: Basile Starynkevitch [local], caml-list > To go beyond that, we would need some help from the language that > would offer some provision for debugging from a special debug keyword, > semantically reminiscent to lazy and assert (as a kind of combined > semantics of both constructs). A compiler flag would then > automatically remove the debugging code (as is done for assert with > the -noassert flag) and the compiler will automatically insert the > (fun () -> ) as it already does in the case of lazy ... count one person at least who would be very interested in such a feature!! exactly for this purpose of log messages with varying debug levels. henri > > [...] > > Actually, I more and more hate printf, both in C and in Ocaml. I > > really believe it is a nightmare. > > Could you elaborate a bit ? We worked hard to provide a clean fully > typed interface to printf and, well ... we like using it :) > > We may have missed the point that makes your printf experience ``a > nightmare'', and having information on that could be helpful to > improve the implementation. > > > A possible suggestion might be to > > add a StopPrintf exception to Printf > > and > > add a tryprintf function to Printf, which takes a prologue function > > as an argument. If the prologue raises an exception, no formatting > > occur; otherwise, tryprintf works like kprintf > > I don't think the problem is in printf. The problem is in the way you > call printf (no printf variant could prevent evaluating the format > string and evaluating the arguments of its call: this is mandatory due > to the semantics of the language). > > > > Best regards, > > Pierre Weis > > INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ > > ------------------- > To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr > Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 6:47 ` Pierre Weis 2004-07-16 7:13 ` Jean-Christophe Filliatre 2004-07-16 7:21 ` henri dubois-ferriere @ 2004-07-16 17:44 ` Markus Mottl 2004-07-19 10:10 ` Pierre Weis 2 siblings, 1 reply; 56+ messages in thread From: Markus Mottl @ 2004-07-16 17:44 UTC (permalink / raw) To: Pierre Weis; +Cc: caml-list On Fri, 16 Jul 2004, Pierre Weis wrote: > Hmm, this sounds extremely lazy to me; so this suggests thunk > programming; hey, we have that in the language, so let's go! > > let log level thunk = > if may_log level then thunk ();; > > ... > > log 2 (fun () -> > eprintf "Argument 1 is hard to compute %d\n" (ackermann x x)) I have used thunks (and lazy values) before, but they are usually syntactically ugly. Instead of: log (fun () -> sprintf "%d" n) I'd rather want to write log "%d" n without having the log function compute a string from an integer if this is not necessary. Would this really be so difficult to support? > That's the way we use to log in the OcamlP3l compiler: we've got no > runtime penalty if there is no necessity to log. Well, you have to create a thunk, but this cost is acceptable to me. I just don't want to clutter my code with thunks + additional sprintf statements. > Moreover, this solution is general enough to accomodate threads, > side effects, or whatever. You always need mutexes if you want to prevent that your output gets messed up by multiple threads. > To me the (fun () -> ) additional verbosity is not so bad: it clearly > emphasizes that nothing at all is evaluated when logging is unnecessary. It's rather the other way round: people using format strings may get the wrong idea that arguments are not converted if there is no output. > To go beyond that, we would need some help from the language that > would offer some provision for debugging from a special debug keyword, > semantically reminiscent to lazy and assert (as a kind of combined > semantics of both constructs). A compiler flag would then > automatically remove the debugging code (as is done for assert with > the -noassert flag) and the compiler will automatically insert the > (fun () -> ) as it already does in the case of lazy ... I don't think it is necessary or even useful to introduce new keywords. A customized, beautiful solution would be possible with camlp4, thunks solve the problem semantically, but look ugly, and some support for a kind of zprintf would be ideal :-) Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 17:44 ` Markus Mottl @ 2004-07-19 10:10 ` Pierre Weis 2004-07-19 10:43 ` Jon Harrop 0 siblings, 1 reply; 56+ messages in thread From: Pierre Weis @ 2004-07-19 10:10 UTC (permalink / raw) To: Markus Mottl; +Cc: pierre.weis, caml-list [...] > > Moreover, this solution is general enough to accomodate threads, > > side effects, or whatever. > > You always need mutexes if you want to prevent that your output gets > messed up by multiple threads. Using thunks, the mutex handling can be done into the log function around the tunk call. > > To me the (fun () -> ) additional verbosity is not so bad: it clearly > > emphasizes that nothing at all is evaluated when logging is unnecessary. > > It's rather the other way round: people using format strings may get > the wrong idea that arguments are not converted if there is no output. They also can have the wrong idea that arguments are not evaluated (since there is no need to convert them to string) which is wrong. [...] > I don't think it is necessary or even useful to introduce new keywords. You are right in general, but in this case we have to deal with a notion that should change the evaluation regime of some expressions. This cannot be implemented without the help of the compiler. > A customized, beautiful solution would be possible with camlp4, thunks > solve the problem semantically, but look ugly, That why I propose to use something similar to assert and lazy: to get a simple way to express this semantics. > and some support for a kind of zprintf would be ideal :-) I'm afraid this would not solve the lazyness problem. Regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-19 10:10 ` Pierre Weis @ 2004-07-19 10:43 ` Jon Harrop 2004-07-21 15:52 ` Pierre Weis 0 siblings, 1 reply; 56+ messages in thread From: Jon Harrop @ 2004-07-19 10:43 UTC (permalink / raw) To: caml-list On Monday 19 July 2004 11:10, Pierre Weis wrote: > They also can have the wrong idea that arguments are not evaluated > (since there is no need to convert them to string) which is wrong. Forgive me if this is irrelevant (I've failed to understand all of your discussion) but can this be tied in with a general way to define functions with specified argument evaluation, e.g. to define your own, short-circuit- evaluated && operator: # (print_endline "1"; false) && (print_endline "2"; true);; 1 - : bool = false # let (&&) a b = a && b;; val ( && ) : bool -> bool -> bool = <fun> # (print_endline "1"; false) && (print_endline "2"; true);; 2 1 - : bool = false Not that I need such a thing... Cheers, Jon. ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-19 10:43 ` Jon Harrop @ 2004-07-21 15:52 ` Pierre Weis 2004-07-21 17:43 ` lazyness in ocaml (was : [Caml-list] kprintf with user formatters) Daniel Bünzli ` (2 more replies) 0 siblings, 3 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-21 15:52 UTC (permalink / raw) To: Jon Harrop; +Cc: caml-list > On Monday 19 July 2004 11:10, Pierre Weis wrote: > > They also can have the wrong idea that arguments are not evaluated > > (since there is no need to convert them to string) which is wrong. > > Forgive me if this is irrelevant (I've failed to understand all of your > discussion) but can this be tied in with a general way to define functions > with specified argument evaluation, e.g. to define your own, short-circuit- > evaluated && operator: > > # (print_endline "1"; false) && (print_endline "2"; true);; > 1 > - : bool = false > # let (&&) a b = a && b;; > val ( && ) : bool -> bool -> bool = <fun> > # (print_endline "1"; false) && (print_endline "2"; true);; > 2 > 1 > - : bool = false > > Not that I need such a thing... > > Cheers, > Jon. Yes this remark is completely relevant: the built-in && and || operators and the if then else construct (considered as a 3 places operator) are the only lazy constructs of the language. Well we now have another extra lazy construction that allows lazy evaluation, as in: let x = lazy (print_string "toto");; val x : unit lazy_t = <lazy> Lazy.force x;; toto- : unit = () So we could imagine a lazy version of printf that only accepts 'a lazy_t arguments and would have to force their evaluation to print them. This way, a global flag may ask lazyprintf to skip everything. The drawback is that you would have to write (lazy expr) for each argument ``expr'' to be printed. Quite a bit intrusive, I think. Best regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-21 15:52 ` Pierre Weis @ 2004-07-21 17:43 ` Daniel Bünzli 2004-07-22 16:28 ` Pierre Weis 2004-07-21 20:41 ` [Caml-list] kprintf with user formatters Jon Harrop 2004-07-22 8:05 ` [Caml-list] wait instruction lehalle@miriad 2 siblings, 1 reply; 56+ messages in thread From: Daniel Bünzli @ 2004-07-21 17:43 UTC (permalink / raw) To: caml-list Le 21 juil. 04, à 17:52, Pierre Weis a écrit : > The drawback is that you would have to write (lazy expr) > for each argument ``expr'' to be printed. Quite a bit intrusive, I > think. I agree. I once tried to port some haskell combinators [1] to ocaml. However I had to stop since using them meant cluttering your code with (lazy e) and lead to unreadable code. A more lightweight notation would be needed in order to do real lazy programming in ocaml. At that time I wondered if specifiying the lazyness when one defines the function and not when one uses it would be a problem (I mean a technical problem, not an ideological one). For example if one defines let f (lazy x) = ... then the application f (x + y) would implicitely mean f (lazy (x + y)). Alternatively something less intrusive than the keyword 'lazy' would be good. Daniel [1] <http://doi.acm.org/10.1145/944705.944727> ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-21 17:43 ` lazyness in ocaml (was : [Caml-list] kprintf with user formatters) Daniel Bünzli @ 2004-07-22 16:28 ` Pierre Weis 2004-07-22 17:03 ` William Lovas 2004-07-22 23:00 ` skaller 0 siblings, 2 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-22 16:28 UTC (permalink / raw) To: Daniel Bünzli; +Cc: caml-list > I agree. I once tried to port some haskell combinators [1] to ocaml. > However I had to stop since using them meant cluttering your code with > (lazy e) and lead to unreadable code. Yes using lazy all over the place is too much! That's why we had once in Caml some implicit way to denote lazy expressions, such as when applying a constructor or building a record. Lazy record fields or lazy constructors had to be declared when defining the type they belongs to; then their usage was implicitely lazy. For example, lazy integer lists were defined as: type llist = {lazy head : int; lazy tail : llist};; Now, {head = expr_head; tail = expr_tail} was automatically compiled as {head = lazy (expr_head); tail = lazy (expr_tail)} (with trivial optimisations if the lazy expressions are simple enough ({head = 1; ...} would build any lazy thunk)). Also an addition to the pattern matching algorithm allowed automatic forcing of lazy parts of data structures. This technic leads to simple and readable lazy programs. > A more lightweight notation would be needed in order to do real lazy > programming in ocaml. At that time I wondered if specifiying the > lazyness when one defines the function and not when one uses it would > be a problem (I mean a technical problem, not an ideological one). > For example if one defines > > let f (lazy x) = ... > > then the application f (x + y) would implicitely mean f (lazy (x + y)). That's a good idea, if only it were compatible with higher-order functionality (and modularity), which I don't know for sure. In my mind, this idea would be a type-based transformation of the source code. The typing rule for lazy function application would be: |~ -: (f : 'a lazy -> 'b) (e : 'a) ---------------------------------- (lazy app) |~ -: (f e : 'b) and the transformation rule on the type annotated abstract syntax trees would be: (f : 'a lazy -> b) (e : 'a) => (f : 'a lazy -> b) (lazy e : 'a lazy) Interestingly enough, the typing rule implies that you not only can omit the lazy keyword at application time: it would be mandatory to omit it! Weel, not so bad, after all ... This has to be precisely ruled out and the necessary proofs have to be made, but I think it could work (including for higher-order functional, map, fold, and so on). I mean, I don't see any trivial counter-example that would ruin this scheme. Wao! If this rule turned out to be usable, it would be a major improvement for lazy evaluation in our favorite language. > Alternatively something less intrusive than the keyword 'lazy' would be > good. > > Daniel > > [1] <http://doi.acm.org/10.1145/944705.944727> Right, but which one ? Best regards, Pierre Weis INRIA, Projet Cristal, http://pauillac.inria.fr/~weis ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-22 16:28 ` Pierre Weis @ 2004-07-22 17:03 ` William Lovas 2004-07-22 23:00 ` skaller 1 sibling, 0 replies; 56+ messages in thread From: William Lovas @ 2004-07-22 17:03 UTC (permalink / raw) To: caml-list On Thu, Jul 22, 2004 at 06:28:51PM +0200, Pierre Weis wrote: > > A more lightweight notation would be needed in order to do real lazy > > programming in ocaml. At that time I wondered if specifiying the > > lazyness when one defines the function and not when one uses it would > > be a problem (I mean a technical problem, not an ideological one). > > For example if one defines > > > > let f (lazy x) = ... > > > > then the application f (x + y) would implicitely mean f (lazy (x + y)). > > [...] > > This has to be precisely ruled out and the necessary proofs have to be > made, but I think it could work (including for higher-order > functional, map, fold, and so on). I mean, I don't see any trivial > counter-example that would ruin this scheme. Wao! If this rule > turned out to be usable, it would be a major improvement for lazy > evaluation in our favorite language. This is reminiscent of the notation in Wadler's paper, "How to add laziness to a strict language, without even being odd"[1]. He even gives the semantics as a translation into the delay/force ("odd") style already supported in O'Caml, similar to this proposal. Perhaps it could even be implemented in camlp4, without any need for type-based transformations. William [1] http://homepages.inf.ed.ac.uk/wadler/papers/lazyinstrict/lazyinstrict.txt ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-22 16:28 ` Pierre Weis 2004-07-22 17:03 ` William Lovas @ 2004-07-22 23:00 ` skaller 2004-07-23 3:32 ` William Lovas 2004-07-28 7:26 ` Pierre Weis 1 sibling, 2 replies; 56+ messages in thread From: skaller @ 2004-07-22 23:00 UTC (permalink / raw) To: Pierre Weis; +Cc: Daniel Bünzli, caml-list On Fri, 2004-07-23 at 02:28, Pierre Weis wrote: > In my mind, this idea would be a type-based transformation of the > source code. The typing rule for lazy function application would be: > > |~ -: (f : 'a lazy -> 'b) (e : 'a) > ---------------------------------- (lazy app) > |~ -: (f e : 'b) > > and the transformation rule on the type annotated abstract syntax > trees would be: > > (f : 'a lazy -> b) (e : 'a) => (f : 'a lazy -> b) (lazy e : 'a lazy) > > Interestingly enough, the typing rule implies that you not only can > omit the lazy keyword at application time: it would be mandatory to > omit it! Weel, not so bad, after all ... > > This has to be precisely ruled out and the necessary proofs have to be > made, but I think it could work (including for higher-order > functional, map, fold, and so on). I mean, I don't see any trivial > counter-example that would ruin this scheme. Wao! If this rule > turned out to be usable, it would be a major improvement for lazy > evaluation in our favorite language. But this looks very dangerous! Its kind of like reference parameters in C++, which make it impossible to tell if f(expr) can modifiy expr or not [without finding which 'f' it is and examining it] In the lazy case it would destroy an important identity: f x <==> let x' = x in f x' With your rule, the LHS might not evaluate x, whereas the RHS would. Of course we already have that: f x y <=/=> let x' = x in y' = y in f x' y' since the RHS guarrantees x is evaluated before y, whilst it happens by chance in the current Ocaml implementation the reverse is true for the LHS. So even if your rule is sound, it might not be a good idea because it breaks 'the substitution principle'. How about sugar: \(expr) <==> lazy expr Since arguments to be lazily evaluated are never variables, they're often going to be surrounded in brackets already, and so this is only a single character .. a lazy way to spell lazy .. and a very easy implementation :) -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-22 23:00 ` skaller @ 2004-07-23 3:32 ` William Lovas 2004-07-28 7:26 ` Pierre Weis 1 sibling, 0 replies; 56+ messages in thread From: William Lovas @ 2004-07-23 3:32 UTC (permalink / raw) To: caml-list On Fri, Jul 23, 2004 at 09:00:49AM +1000, skaller wrote: > How about sugar: > > \(expr) <==> lazy expr > > Since arguments to be lazily evaluated are never variables, > they're often going to be surrounded in brackets already, > and so this is only a single character .. > a lazy way to spell lazy .. and a very easy implementation :) ... and this is a lot like Okasaki's $ proposal, also mentioned in Wadler's paper on lazy notation in strict languages[1]. There really is nothing new under the sun :) William [1] http://homepages.inf.ed.ac.uk/wadler/papers/lazyinstrict/lazyinstrict.txt ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-22 23:00 ` skaller 2004-07-23 3:32 ` William Lovas @ 2004-07-28 7:26 ` Pierre Weis 2004-07-28 8:06 ` skaller 2004-07-28 10:17 ` Jason Smith 1 sibling, 2 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-28 7:26 UTC (permalink / raw) To: skaller; +Cc: pierre.weis, daniel.buenzli, caml-list [...] > But this looks very dangerous! Yes: lazyness in the presence of side-effects is tricky. But don't worry, that's not the introduction of this new rule that is dangerous, it is the concept of lazy evaluation and more importantly the mixing of lazy evaluation and strict evaluation that is difficult in the presence of side effects. > Its kind of like reference parameters in C++, which make > it impossible to tell if f(expr) can modifiy expr or not > [without finding which 'f' it is and examining it] I cannot understand that one. We have that in Caml already and we had it from the very begining of Caml (1984). For instance, if I write f (expr) could you tell me ``if f(expr) can modifiy expr or not [without finding which 'f' it is and examining it]'' ? To the best of my knowledge, the answer is no. To the best of my knowledge, nobody never complained about that feature. > > In the lazy case it would destroy an important identity: > > f x <==> let x' = x in f x' > > With your rule, the LHS might not evaluate x, whereas the RHS > would. Yes, that's exactly what we want: if (f e) is a lazy application you don't know if e is evaluated or not. This is just what lazyness is about ! Also, I didn't know that such an ``important identity'' stands for Caml expressions. Except in the trivial case where ``x'' just denotes a variable in the statment. In this case, the statment still holds with the new rule :) > Of course we already have that: > > f x y <=/=> let x' = x in y' = y in f x' y' > > since the RHS guarrantees x is evaluated before y, > whilst it happens by chance in the current Ocaml implementation > the reverse is true for the LHS. So what? Is the ``important identity'' wrong after all, being wrong in this case ? Or do you suggest to suppress currying in order to restore the ``important identity'' ? > So even if your rule is sound, it might not be a good idea > because it breaks 'the substitution principle'. There is nothing such as your ``substitution principle'' in Caml, except if we restrict the language to truly trivial expressions (as soon as expressions may incoporate basic operators such as the integer addition your ``principle'' does not stand anymore). > How about sugar: > > \(expr) <==> lazy expr > > Since arguments to be lazily evaluated are never variables, Wait a minute: do you mean I cannot write f e, if e is just a variable? If the answer is yes, your suggestion breaks something important (we still want to apply a function to any expression of the suitable type); if the answer is no then you would need to write f \x as you now have to write f (lazy x) with the current compiler. Or you would have to implement something really strange to handle f e differently if the expression e is a variable or not. Best regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-28 7:26 ` Pierre Weis @ 2004-07-28 8:06 ` skaller 2004-07-28 8:29 ` Daniel Bünzli 2004-07-28 9:13 ` Pierre Weis 2004-07-28 10:17 ` Jason Smith 1 sibling, 2 replies; 56+ messages in thread From: skaller @ 2004-07-28 8:06 UTC (permalink / raw) To: Pierre Weis; +Cc: daniel.buenzli, caml-list On Wed, 2004-07-28 at 17:26, Pierre Weis wrote: > There is nothing such as your ``substitution principle'' in Caml, > except if we restrict the language to truly trivial expressions (as > soon as expressions may incoporate basic operators such as the integer > addition your ``principle'' does not stand anymore). I thought: let x = expr in f x and f expr are identical in all circumstances in Ocaml for all terms 'expr', I must have missed something .. do you have a counter example? -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-28 8:06 ` skaller @ 2004-07-28 8:29 ` Daniel Bünzli 2004-07-28 9:13 ` Pierre Weis 1 sibling, 0 replies; 56+ messages in thread From: Daniel Bünzli @ 2004-07-28 8:29 UTC (permalink / raw) To: skaller; +Cc: Pierre Weis, caml-list Le 28 juil. 04, à 10:06, skaller a écrit : > do you have a counter example? let f c = let a = input_byte c in let b = input_byte c in (a,b) let f' c = (input_byte c, input_byte c) f and f' do not produce the same pair on my platform. Daniel ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-28 8:06 ` skaller 2004-07-28 8:29 ` Daniel Bünzli @ 2004-07-28 9:13 ` Pierre Weis 2004-07-28 9:36 ` skaller 2004-07-28 9:38 ` skaller 1 sibling, 2 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-28 9:13 UTC (permalink / raw) To: skaller; +Cc: pierre.weis, daniel.buenzli, caml-list > On Wed, 2004-07-28 at 17:26, Pierre Weis wrote: > > > There is nothing such as your ``substitution principle'' in Caml, > > except if we restrict the language to truly trivial expressions (as > > soon as expressions may incoporate basic operators such as the integer > > addition your ``principle'' does not stand anymore). > > I thought: > > let x = expr in f x > > and > > f expr > > are identical in all circumstances in Ocaml > for all terms 'expr', I must have missed > something .. do you have a counter example? We have to precisely state the statement here: - if you mean that ``f'' is just an ident (more precisely, a lowercase ident in the Caml parser parlance) bound to a unary function, then the two expressions are equivalent. - if f can have more than one argument, then the two expressions are obviously not equivalent since the first one fixes the order of evaluation when the second does not. This is true in particular if f is ( + ): let x = expr in expr2 + x and expr2 + x may not evaluate the same (depending on the compiler: a lot of flamewar already occurred on this list about that feature). - if f can be more than a lowercase ident and in particular if f can introduce a lazy construction, then the two expressions are not equivalent (as desired), since the first one explicitely evaluates expr when the second may not. Consider f being ``lazy'' and expr being ``failwith "evaluated"'': # let x = failwith "evaluated" in lazy x;; Exception: Failure "evaluated". # lazy (failwith "evaluated");; - : 'a lazy_t = <lazy> Here, you check again that lazy evaluation just breaks the eagerness of the language (and hence breaks your ``identity'' a bit more): lazyness changes the default evaluation regime, just as desired. It's no surprise, something has changed after the introduction of lazyness! What I propose is a smoother interaction with the rest of the language with the (re)-introduction of lazy constructors, lazy labels and a new typing (and compilation) rule to facilitate the use of lazy functions. Best regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-28 9:13 ` Pierre Weis @ 2004-07-28 9:36 ` skaller 2004-07-28 9:38 ` skaller 1 sibling, 0 replies; 56+ messages in thread From: skaller @ 2004-07-28 9:36 UTC (permalink / raw) To: Pierre Weis; +Cc: daniel.buenzli, caml-list On Wed, 2004-07-28 at 19:13, Pierre Weis wrote: > > On Wed, 2004-07-28 at 17:26, Pierre Weis wrote: > > > > > There is nothing such as your ``substitution principle'' in Caml, > > > except if we restrict the language to truly trivial expressions (as > > > soon as expressions may incoporate basic operators such as the integer > > > addition your ``principle'' does not stand anymore). > > > > I thought: > > > > let x = expr in f x > > > > and > > > > f expr > > > > are identical in all circumstances in Ocaml > > for all terms 'expr', I must have missed > > something .. do you have a counter example? > > We have to precisely state the statement here: > > - if you mean that ``f'' is just an ident (more precisely, a > lowercase ident in the Caml parser parlance) bound to a unary > function, then the two expressions are equivalent. f is a function constant, but i didn't specify unary.. > - if f can have more than one argument, then the two expressions are > obviously not equivalent since the first one fixes the order of > evaluation when the second does not. OK, thanks. You are right. Given let x = f e in x y and (f e) y might evaluate e and y in different orders. Sorry -- you did already point this out too, i just didn't see it :) -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-28 9:13 ` Pierre Weis 2004-07-28 9:36 ` skaller @ 2004-07-28 9:38 ` skaller 1 sibling, 0 replies; 56+ messages in thread From: skaller @ 2004-07-28 9:38 UTC (permalink / raw) To: Pierre Weis; +Cc: daniel.buenzli, caml-list On Wed, 2004-07-28 at 19:13, Pierre Weis wrote: > What I propose is a smoother interaction with the rest of the language > with the (re)-introduction of lazy constructors, lazy labels and a new > typing (and compilation) rule to facilitate the use of lazy functions. OK: I said this looked dangerous, but the resulting discussion convinces me that it could be worth it, since the guarrantees I thought might be broken didn't really exist in the first place. -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-28 7:26 ` Pierre Weis 2004-07-28 8:06 ` skaller @ 2004-07-28 10:17 ` Jason Smith 2004-07-28 12:31 ` skaller 1 sibling, 1 reply; 56+ messages in thread From: Jason Smith @ 2004-07-28 10:17 UTC (permalink / raw) To: caml-list Hello, first off I come from a Haskell background, and especially ghc so I might be a little off key here, but I thought I'd add my thoughts come what may. Also I'm a newbie so go easy if I'm off base :) (which is more then likely!) > I cannot understand that one. We have that in Caml already and we had > it from the very begining of Caml (1984). For instance, if I write > > f (expr) > > could you tell me ``if f(expr) can modifiy expr or not [without > finding which 'f' it is and examining it]'' ? > > To the best of my knowledge, the answer is no. Well thats kinda what strictness analysis does. If f is going to use the expression then we evaluate it before entering the function so we don't have to pass around THUNKS. But yes we have to know what the 'f' is were playing with. > To the best of my knowledge, nobody never complained about that feature. Its an optimization that is performed regularly in the ghc compiler, and yeah no one complains about its abscence! :) > > > In the lazy case it would destroy an important identity: > > > > f x <==> let x' = x in f x' > > > > With your rule, the LHS might not evaluate x, whereas the RHS > > would. I'm not exactly sure why u defined the substitution principle like this, the syntax should be a non-issue. The way I learned it (from Mitchells excellent book) was the following. The substitution lemma intuitively says that susbtituting a term N for a variable x in M is the same effect on the meaning of M as changing the environment so that the value of x is the value of N. The meaning is what matters, not its syntactic form. If we use just plain alegbra here, where S is the set of sorts, G the environment assigning types to terms, we can define it as given M 'elem' Terms(S, G, x:s'), and N 'elem' Terms(S, G), so that [N/x]M 'elem' Terms(S, G). Then for any environment E, we can say that the denotational meaning (given by the meaning function < >) for each is the same, i.e. <[N/x]M>E == <M>E{x -> a} where a = <N>E is the meaning of N at E. In the above, the meanings of an evaluated expression and an unevaluated expression are as far as I'm aware identical. In the prescence of side-effects this complicates the operational semantics (and invalidates equivalences in the denotational semantics), because side-effects change the storage semantics of the environment and can invalidate the meaning function. For example when we substitute N for x in M, evaluating N may change the meaning of a variable other then x free in M. There are a number of papers by Sullivan and Wand discussing various transformations like lambda lifting in a denotational model based on a operational based term model where interaction is the basic observable, and they don't consider the store as the final part of the congruence proof. Anywayz, the problem with the above is that this equivelence already does not hold in Ocaml'. In Haskell the above identity phrased as it is, would hold, because we don't have side effects. Threading of the world through the IO Monad forces the same evaluation order for both expressions. > Also, I didn't know that such an ``important identity'' stands for > Caml expressions. Except in the trivial case where ``x'' just denotes > a variable in the statment. In this case, the statment still holds with > the new rule :) >From what I can see yes it is broken because of side-effects, we cannot guarentee that the two phrases are equivalent in the standard denotational semantics. > > Of course we already have that: > > > > f x y <=/=> let x' = x in y' = y in f x' y' > > > > since the RHS guarrantees x is evaluated before y, > > whilst it happens by chance in the current Ocaml implementation > > the reverse is true for the LHS. > > So what? Is the ``important identity'' wrong after all, being wrong in > this case ? Or do you suggest to suppress currying in order to restore > the ``important identity' I'm a bit behind the discussion but I think the original poster was just pointing out that we can impose AOR reduction explicitly by using the let constructs. Cheers, Jason. ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: lazyness in ocaml (was : [Caml-list] kprintf with user formatters) 2004-07-28 10:17 ` Jason Smith @ 2004-07-28 12:31 ` skaller 0 siblings, 0 replies; 56+ messages in thread From: skaller @ 2004-07-28 12:31 UTC (permalink / raw) To: Jason Smith; +Cc: caml-list On Wed, 2004-07-28 at 20:17, Jason Smith wrote: > > > f x <==> let x' = x in f x' > I'm not exactly sure why u defined the substitution principle like this, the > syntax should be a non-issue. I'm talking about programming in a specific language Ocaml, defined in terms of its syntax -- so there is no choice but to talk about it in those terms. Ocaml is Ocaml not lambda calculus :) -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-21 15:52 ` Pierre Weis 2004-07-21 17:43 ` lazyness in ocaml (was : [Caml-list] kprintf with user formatters) Daniel Bünzli @ 2004-07-21 20:41 ` Jon Harrop 2004-07-22 15:39 ` Pierre Weis 2004-07-22 8:05 ` [Caml-list] wait instruction lehalle@miriad 2 siblings, 1 reply; 56+ messages in thread From: Jon Harrop @ 2004-07-21 20:41 UTC (permalink / raw) To: caml-list On Wednesday 21 July 2004 16:52, Pierre Weis wrote: > Yes this remark is completely relevant: I knew it. ;-) > the built-in && and || > operators and the if then else construct (considered as a 3 places > operator) are the only lazy constructs of the language. Is "match pred with true -> expr1 | false -> expr2" not equivalent to "if pred then expr1 else expr2"? If so, isn't pattern matching a fourth lazy construct? Just after I wrote that last post I realised that this approach could actually be useful in numerical contexts. As a trivial example, integer multiply could lazily evaluate its second argument (only when it is pure, if conventional semantics are to be preserved), not needing it if the first argument is zero. This may be useful in more complicated settings, i.e. when dealing with data structures rather than primitive types and when predicates over the data structure can be evaluated much more quickly than the corresponding expression. Such functionality can, of course, be implemented in vanilla OCaml. But I'd like to see a language which allowed mathematics to be expressed in a notation as close to conventional written form as possible (although I prefer type distinctions, like "+" vs "+.") whilst retaining efficiency (I'd also like to see deforesting, e.g. in vector expressions without having to resort to maps, folds etc.). Perhaps an OCaml -> OCaml optimising compiler would be a good project for someone? That way implementation details and their benefits can be examined without having to touch the OCaml compilers. I think it could be quite fun to play with such a thing... Cheers, Jon. ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-21 20:41 ` [Caml-list] kprintf with user formatters Jon Harrop @ 2004-07-22 15:39 ` Pierre Weis 2004-07-22 22:16 ` [Caml-list] lazy evaluation: [Was: kprintf with user formatters] skaller 2004-07-22 22:42 ` [Caml-list] kprintf with user formatters skaller 0 siblings, 2 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-22 15:39 UTC (permalink / raw) To: Jon Harrop; +Cc: caml-list [...] > Is "match pred with true -> expr1 | false -> expr2" not > equivalent to "if pred then expr1 else expr2"? If so, isn't pattern > matching a fourth lazy construct? Yes indeed, if you consider ``match'' as an operator, which is a bit hairy, since match would be a (2n+1)-ary operator (for any given positive integer n), taking as input 1 expression (the one to be matched) and n (pattern, expression) pairs to match the expression. Given that there is no notion of evaluation semantics associated to a pattern (in the sense of the evaluation of expression) this would be strange. However, the very match expression you mentioned has indeed something of a lazyness behavior, since it is indeed equivalent of an ``if ... then ... else ...'' construct, as I know you know :) > Just after I wrote that last post I realised that this approach > could actually be useful in numerical contexts. As a trivial > example, integer multiply could lazily evaluate its second argument > (only when it is pure, if conventional semantics are to be > preserved), not needing it if the first argument is zero. I don't think the gain would overcome the cost of having to create thunks in practice. On the other hand, taht would lead to evaluate the operation 0 * expr to 0, even if the computation of expr would lead to divergence (never terminates or fails). It's mathematically kind of weird, I think. For instance, you would have a hard time to persuade a matematician that 0 * ln (0) is well-defined and evaluates to 0, ``because ln (0) has not to be considered at all given the left operand''. Hence, as far as I know, arithmetics operators are always considered strict in lazy languages. > This may be useful in more complicated settings, i.e. when dealing > with data structures rather than primitive types and when predicates > over the data structure can be evaluated much more quickly than the > corresponding expression. I'm a bit lost here. Could you explain a bit ? > Such functionality can, of course, be implemented in vanilla > OCaml. But I'd like to see a language which allowed mathematics to > be expressed in a notation as close to conventional written form as > possible (although I prefer type distinctions, like "+" vs "+.") > whilst retaining efficiency (I'd also like to see deforesting, > e.g. in vector expressions without having to resort to maps, folds > etc.). Yes, we all want such a language. Caml is the best approximation I know, wrt a perfect match between efficiency and notational facility. > Perhaps an OCaml -> OCaml optimising compiler would be a good > project for someone? That way implementation details and their > benefits can be examined without having to touch the OCaml > compilers. I think it could be quite fun to play with such a > thing... > > Cheers, > Jon. Yes, many people have dreamed upon (or even have planned to do) such a tool in the past. These days, the availability of the camlp4 tools would help a lot to perform such a goal... Best regards, Pierre Weis INRIA, Projet Cristal, http://pauillac.inria.fr/~weis ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* [Caml-list] lazy evaluation: [Was: kprintf with user formatters] 2004-07-22 15:39 ` Pierre Weis @ 2004-07-22 22:16 ` skaller 2004-07-22 22:42 ` [Caml-list] kprintf with user formatters skaller 1 sibling, 0 replies; 56+ messages in thread From: skaller @ 2004-07-22 22:16 UTC (permalink / raw) To: caml-list On Fri, 2004-07-23 at 01:39, Pierre Weis wrote: > However, the very match expression you > mentioned has indeed something of a lazyness behavior, since it is > indeed equivalent of an ``if ... then ... else ...'' construct, as > I know you know :) I'm intrigued! Felix has a side-effect free functional subsystem, and I expected this to buy considerable optimisation opportunities unavailable in Ocaml: in particular, any functional code which is normally evaluated eagerly can always be evaluated lazily (which the optimiser effects by converting it to procedural goto-spagetti). However, erroneous or non-terminating lazy code can't be prematurely evaluated in either language I'd kind of assumed this could be done in Felix, but it is clear now this isn't the case. This seems to indicate in hybrid languages like Ocaml and Felix well specified parts of the language must be deemed eager or lazy: both languages support expicitly procedural constructions, however even the functional code in both languages seems to need the evaluation time specified (to more extent than I'd believed previously..) Curiously this seems to indicate that in the long run Haskell compilers should be able to generate more efficient code if only the optimisers are smart enough to prove it is both correct and efficient to evaluate something prematurely. One of my friends is actually doing a thesis on this. His technique is basically to make everything eager by default, and then upgrade it to lazy if necessary (rather than the other way around). -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-22 15:39 ` Pierre Weis 2004-07-22 22:16 ` [Caml-list] lazy evaluation: [Was: kprintf with user formatters] skaller @ 2004-07-22 22:42 ` skaller 1 sibling, 0 replies; 56+ messages in thread From: skaller @ 2004-07-22 22:42 UTC (permalink / raw) To: Pierre Weis; +Cc: Jon Harrop, caml-list On Fri, 2004-07-23 at 01:39, Pierre Weis wrote: > For instance, you would have a hard time to persuade a > matematician that > > 0 * ln (0) > > is well-defined and evaluates to 0, ``because ln (0) has not to be > considered at all given the left operand''. Actually, this IS the case in many languages such as C. 0 is not in the domain of ln. Therefore, the result is undefined when you apply ln to 0 because you're applying a function to a value outside its domain. In language standards it is sometimes said that the result is undefined in such cases, which means that the compiler can generate code to do anything it wants in such cases. In particular it can return 0 and remain conforming and therefore it can apply the shortcut evaluation. This is NOT the case if the language standard specifies an exception must be thrown, or NaN or +Inf returned, which is generally a very bad idea precisely because it makes the semantics determinate and thus defeats the optimisation which could otherwise be obtained by using the usual mathematical law 0 * x = 0. C is very careful to leave lots of things undefined. This issue actually arose directly on the C++ Standards Committee, except the function was division not ln. The question was whether a compiler was allowed and/or required to issue a diagnostic error message given: main() { return 1/0; } Note that it is possible to prove IN THIS CASE that the program will always fail by dividing by zero. However, it isn't always so obvious -- so you simply cannot require a diagnostic. Indeed, one can argue -- and someone DID argue -- that even if the program always fails when executed .. who knows if it is executed? The code must be generated, C compiler can issue a warning but it is NOT allowed to reject the program. It must actually generated code which can be executed .. even though that code can do anything (Aas far as I can remember that was the interpretation..) -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* [Caml-list] wait instruction 2004-07-21 15:52 ` Pierre Weis 2004-07-21 17:43 ` lazyness in ocaml (was : [Caml-list] kprintf with user formatters) Daniel Bünzli 2004-07-21 20:41 ` [Caml-list] kprintf with user formatters Jon Harrop @ 2004-07-22 8:05 ` lehalle@miriad 2004-07-22 8:40 ` Olivier Andrieu 2004-07-22 10:33 ` Vitaly Lugovsky 2 siblings, 2 replies; 56+ messages in thread From: lehalle@miriad @ 2004-07-22 8:05 UTC (permalink / raw) To: caml-list Hi, I want a function that allow my code to wait for m milliseconds before continuing, and I need a cross-platform function (win and linux) to perfom that. any idea ? thanks, charles -- Charles-Albert Lehalle --- MIRIAD Technologies Responsable Développements Algorithmiques et Applications mailto:charles.lehalle@miriadtech.com keyserver: http://pgp.mit.edu/ tel : 0156431816 - fax: 0156431828 8 av Hoche - 75008 PARIS - FRANCE ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] wait instruction 2004-07-22 8:05 ` [Caml-list] wait instruction lehalle@miriad @ 2004-07-22 8:40 ` Olivier Andrieu 2004-07-22 10:35 ` lehalle@miriad 2004-07-22 10:33 ` Vitaly Lugovsky 1 sibling, 1 reply; 56+ messages in thread From: Olivier Andrieu @ 2004-07-22 8:40 UTC (permalink / raw) To: charles.lehalle; +Cc: caml-list "lehalle@miriad" [Thu, 22 Jul 2004]: > Hi, > > I want a function that allow my code to wait for m milliseconds > before continuing, and I need a cross-platform function (win and > linux) to perfom that. any idea ? select ? let msleep ms = let _ = Unix.select [] [] [] (float ms /. 1000.) in () -- Olivier ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] wait instruction 2004-07-22 8:40 ` Olivier Andrieu @ 2004-07-22 10:35 ` lehalle@miriad 0 siblings, 0 replies; 56+ messages in thread From: lehalle@miriad @ 2004-07-22 10:35 UTC (permalink / raw) To: caml-list; +Cc: Olivier Andrieu On Thu, 22 Jul 2004 10:40:51 +0200 (CEST), Olivier Andrieu <andrieu@ijm.jussieu.fr> wrote: > select ? > let msleep ms = > let _ = Unix.select [] [] [] (float ms /. 1000.) in () thank you, it is indeed what I wanted. I will use it for my (now traditionnal) open source "summer game", that I program in ocaml for 2 years, the last year release was dominocaml (a domino game engine with an interface with any language to implement "AI players") and this year will be an hybrid tetris-winmine game called BoCaL, you can find its actual release here: http://sourceforge.net/project/showfiles.php?group_id=72934&package_id=123433&release_id=254953 more seriously I will try to upgrade ocamaweb (a "widely" used literate programming tool in ocaml) next week including new features accordingly to the new MATLAB release and allowing it to work with ANY programming language. if someone here already use it and wants to give me advices : monday is the dead line. charles ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] wait instruction 2004-07-22 8:05 ` [Caml-list] wait instruction lehalle@miriad 2004-07-22 8:40 ` Olivier Andrieu @ 2004-07-22 10:33 ` Vitaly Lugovsky 1 sibling, 0 replies; 56+ messages in thread From: Vitaly Lugovsky @ 2004-07-22 10:33 UTC (permalink / raw) To: lehalle@miriad; +Cc: caml-list On Thu, 22 Jul 2004, lehalle@miriad wrote: > Hi, > > I want a function that allow my code to wait for m > milliseconds before > continuing, and I need a cross-platform function (win and > linux) to perfom > that. any idea ? I am using OcamlSDL bindings for this, even in the scientific computations applications. ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 13:45 ` Markus Mottl 2004-07-15 14:22 ` Basile Starynkevitch [local] @ 2004-07-16 6:17 ` Pierre Weis 2004-07-16 17:14 ` Markus Mottl 1 sibling, 1 reply; 56+ messages in thread From: Pierre Weis @ 2004-07-16 6:17 UTC (permalink / raw) To: Markus Mottl; +Cc: basile.starynkevitch, caml-list > On Thu, 15 Jul 2004, Basile Starynkevitch [local] wrote: > > I don't understand what this zprintf function should be, > > It should parse the format string, and ignore format arguments following > it. > > > but the above > > log proposal behave strangely (and perhaps unsafely) : > > > > # log false "a=%d s=%S\n%!" 1 "xyz";; > > - : unit = <unknown constructor> > > The reason for this is that it returns a function and not a unit value. > Unless you parse the format string, there is no way you can know when > to stop eating arguments to return a value. That's the debugger view of the problem :) The Caml compiler's view is simpler: you broke the type system, you get wrong results! > I don't think that this hack will be too dangerous. You might get an > exception 'Invalid_argument "equal: functional value"' if you want to > compare those fancy unit-values, which is about the worst thing you > can achieve. But who would want to compare unit-values anyway? I have no time to try and find a way to get a bus error with that one but I would not be glad to use software based on such a ugly hack that is not proved harmless in any case. > > For what it's worth, long time ago, I ended writing a camlp4 extension > > for a similar logging (or tracing purpose) see file README.trace and > > pa_trace.ml of > > http://cvs.sourceforge.net/viewcvs.py/poesia/PoesiaSoft/PoesiaMonIcap/ > > The preprocessor is not good enough for me. I would like to change > log levels at runtime, because the application is a server which should > run permanently. ``the application is a server which should run permanently'' ? Wao! May I suggest no to use Obj.magic too often for this kind of application ? Especially when you ``don't think that this hack will be too dangerous'': this hack could kill your server not too permanently! Best regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 6:17 ` [Caml-list] kprintf with user formatters Pierre Weis @ 2004-07-16 17:14 ` Markus Mottl 2004-07-19 10:00 ` Pierre Weis 0 siblings, 1 reply; 56+ messages in thread From: Markus Mottl @ 2004-07-16 17:14 UTC (permalink / raw) To: Pierre Weis; +Cc: caml-list On Fri, 16 Jul 2004, Pierre Weis wrote: > ``the application is a server which should run permanently'' ? Wao! > May I suggest no to use Obj.magic too often for this kind of > application ? Especially when you ``don't think that this hack will > be too dangerous'': this hack could kill your server not too permanently! Well, I suppose you don't want to imply that I should refrain from using modules Printf and Format? They are full of Obj.magic! I have definitely given it some thought whether there could be some kind of unsound use of return values, but I didn't find anything, because unit-values are always ignored. Any other solution I have seen so far is much more complicated: it either requires the use of a preprocessor, thunking or the use of lazy values (I had already used them before - very unwieldy) or forces unnecessary computations even if some action at the current log level shouldn't be logged. The only sufficiently efficient, elegant and safe solution would be to introduce some kind of flag into the fprintf_out function in Printf so that it doesn't call string conversion functions. Or provide a dummy function that just parses the format string and removes arguments. This way a zprintf-function could be put into the interface. Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 17:14 ` Markus Mottl @ 2004-07-19 10:00 ` Pierre Weis 0 siblings, 0 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-19 10:00 UTC (permalink / raw) To: Markus Mottl; +Cc: pierre.weis, caml-list [...] > Well, I suppose you don't want to imply that I should refrain from using > modules Printf and Format? They are full of Obj.magic! I certainly not want to imply that you should refrain from using Printf, Format, Scanf, and also the ocaml interactive system, given that they all use Obj.magic. However, all those uses of Obj.magic have a strong theoretical justification. In the best case they have been proved to be perfectly sound. In any case, we certainly never have a proof that some of those Obj.magic uses can lead to a wrong value (as a closure supposed to have type unit would be). > I have definitely given it some thought whether there could be some > kind of unsound use of return values, but I didn't find anything, > because unit-values are always ignored. Thank you for given some thought about unsound use of Obj.magic on the compiler. If you ever discover one (out of Marshall), please let us know, we will be glad to modify it :) However, I'm glad that you ``didn't find anything''. I should say that this is not, as you guessed, ``because unit-values are always ignored'': the reason is more likely to be that we always have strong evidence that those Obj.magic occurrences are harmless and extremely hard to eliminate. > Any other solution I have seen so far is much more complicated: it either > requires the use of a preprocessor, thunking or the use of lazy values > (I had already used them before - very unwieldy) or forces unnecessary > computations even if some action at the current log level shouldn't > be logged. > > The only sufficiently efficient, elegant and safe solution would be to > introduce some kind of flag into the fprintf_out function in Printf so > that it doesn't call string conversion functions. Or provide a dummy > function that just parses the format string and removes arguments. > This way a zprintf-function could be put into the interface. Once more you do not solve the problem of arguments useless evaluation. I'm convinced that the more elegant way is to introduce some support for logging into the system. Regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 7:39 ` Damien 2004-07-15 12:19 ` Markus Mottl @ 2004-07-16 6:02 ` Pierre Weis 2004-07-16 8:42 ` Damien 2004-07-16 16:52 ` Markus Mottl 1 sibling, 2 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-16 6:02 UTC (permalink / raw) To: Damien; +Cc: caml-list [...] > I had the same problem a month ago, > I ended with the following ugly function: > > let log b fmt = > if b then Printf.printf fmt > else > let rec f x = Obj.magic f in > f fmt > (* val f: bool -> ('a, out_channel, unit) format -> 'a *) > > (I think this is safe since f just eats its arguments, > and gets typed with "-rectypes" : ('b->'a) as 'a) No, this is not safe: you break the type system and create buggy values like that. # let log b fmt = if b then Printf.printf fmt else let rec f x = Obj.magic f in f fmt;; val log : bool -> ('a, out_channel, unit) format -> 'a = <fun> # log false "";; - : unit = <unknown constructor> # let x = log false "";; val x : unit = <unknown constructor> # Marshal.to_string;; - : 'a -> Marshal.extern_flags list -> string = <fun> # Marshal.to_string x [];; Exception: Invalid_argument "output_value: abstract value (outside heap)". There is clearly something wrong! > maybe a function "zprintf" could be added to Printf and Format to do > this job ? It is overkill to introduce a new printf function just for that case. I suggest we try a bit harder to find an acceptable solution without introducing zprintf :) Best regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 6:02 ` Pierre Weis @ 2004-07-16 8:42 ` Damien 2004-07-19 9:00 ` Pierre Weis 2004-07-16 16:52 ` Markus Mottl 1 sibling, 1 reply; 56+ messages in thread From: Damien @ 2004-07-16 8:42 UTC (permalink / raw) To: caml-list your CPS solution is fine (except its syntax), but I would like to defend my solution... On Fri, 16 Jul 2004 08:02:27 +0200 (MET DST) Pierre Weis wrote: > # let log b fmt = > if b then Printf.printf fmt else > let rec f x = Obj.magic f in f fmt;; > val log : bool -> ('a, out_channel, unit) format -> 'a = <fun> > # let x = log false "";; > val x : unit = <unknown constructor> > # Marshal.to_string x [];; > Exception: Invalid_argument "output_value: abstract value (outside > heap)". > > There is clearly something wrong! then, what about the following :-) # Marshal.to_string (fun () -> ()) [];; Exception: Invalid_argument "output_value: abstract value". > It is overkill to introduce a new printf function just for that case. maybe... but it is not to hard to implement (after a quick look at printf.ml) without the "invalid unit value" problem: << let count fmt = (* this function could be implemented more safely using Printf internals*) let s = string_of_format fmt in let rec aux a i = match String.unsafe_get s i with | '%' -> (match String.unsafe_get s (i+1) with | '%' -> aux a (i+2) | '!' -> aux a (i+2) | 'a' -> aux (a+2) (i+2) | _ -> aux (a+1) (i+2)) | '\000' -> a | _ -> aux a (i+1) in aux 0 0 let rec eat = function | 0 -> Obj.magic () | i -> Obj.magic (fun x -> eat (i-1)) let zprintf (fmt: ('a, _, _, _) format4): 'a = eat (count fmt) let log b = if b then Printf.printf else zprintf >> if (like me), you don't like Obj.magic, please have look at printf.ml... regards, damien ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 8:42 ` Damien @ 2004-07-19 9:00 ` Pierre Weis 0 siblings, 0 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-19 9:00 UTC (permalink / raw) To: Damien; +Cc: caml-list [...] > > # Marshal.to_string x [];; > > Exception: Invalid_argument "output_value: abstract value (outside > > heap)". > > > > There is clearly something wrong! > then, what about the following :-) > # Marshal.to_string (fun () -> ()) [];; > Exception: Invalid_argument "output_value: abstract value". As you may have guessed this is a completely different problem: marshalling functions is hard and had always be. It is no surprise we fail in this case. On the other hand, the value () is a basic one and had always been handled properly everywhere in the compiler and runtime: introducing a strange (if not buggy) behaviour for () is not desirable to say the least. > but it is not to hard to implement (after a quick look at printf.ml) > without the "invalid unit value" problem: The implementors will never accept to introduce an ``invalid unit value'' into the standard library. Thanks God, we never did so, and I'm pretty sure that if we had, the language and the compiler would not have the quality they have now. However, your solution does not solve the problem of the useless evaluation of the arguments of the call to printf. For that, you need the help of the compiler and a lazy construct and/or a flag of the compiler to pay nothing when you should not have to pay. Best regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 6:02 ` Pierre Weis 2004-07-16 8:42 ` Damien @ 2004-07-16 16:52 ` Markus Mottl 2004-07-19 9:28 ` Pierre Weis 1 sibling, 1 reply; 56+ messages in thread From: Markus Mottl @ 2004-07-16 16:52 UTC (permalink / raw) To: Pierre Weis; +Cc: caml-list On Fri, 16 Jul 2004, Pierre Weis wrote: > No, this is not safe: you break the type system and create buggy > values like that. True, but unit values are not very useful so if the user ignores them (as usual), there won't be any problems. > # let log b fmt = > if b then Printf.printf fmt else > let rec f x = Obj.magic f in f fmt;; > val log : bool -> ('a, out_channel, unit) format -> 'a = <fun> > # log false "";; > - : unit = <unknown constructor> > # let x = log false "";; > val x : unit = <unknown constructor> > # Marshal.to_string;; > - : 'a -> Marshal.extern_flags list -> string = <fun> > # Marshal.to_string x [];; > Exception: Invalid_argument "output_value: abstract value (outside > heap)". > > There is clearly something wrong! Oh, come on, don't prohibit my use of Obj.magic by demonstrating strange interactions with the equally unsafe Marshal-module ;-) Btw., what has happened to generics? They were said to solve problems associated with type safety and I/O. Any intentions to put them into the experimental CVS-tree of OCaml? Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-16 16:52 ` Markus Mottl @ 2004-07-19 9:28 ` Pierre Weis 0 siblings, 0 replies; 56+ messages in thread From: Pierre Weis @ 2004-07-19 9:28 UTC (permalink / raw) To: Markus Mottl; +Cc: pierre.weis, caml-list [...] > > # log false "";; > > - : unit = <unknown constructor> [...] > > There is clearly something wrong! > > Oh, come on, don't prohibit my use of Obj.magic by demonstrating strange > interactions with the equally unsafe Marshal-module ;-) I cannot and would not like to prohibit your uses of Obj.magic. Go on if you dare. I just pointed out that this particular use of Obj.magic created a value that is considered by the Caml system as an ``<unknown constructor>'': a value that breaks the compiler invariant so deeply that it cannot print it. This is a bad property that could eventually bit your program and crash it. > Btw., what has happened to generics? They were said to solve problems > associated with type safety and I/O. Any intentions to put them into > the experimental CVS-tree of OCaml? That's still something to do... Regards, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 0:17 ` Markus Mottl 2004-07-15 7:30 ` David MENTRE 2004-07-15 7:39 ` Damien @ 2004-07-15 22:20 ` Pierre Weis 2004-07-15 23:01 ` Markus Mottl 2004-07-16 16:17 ` james woodyatt 3 siblings, 1 reply; 56+ messages in thread From: Pierre Weis @ 2004-07-15 22:20 UTC (permalink / raw) To: Markus Mottl; +Cc: pierre.weis, caml-list > On Wed, 14 Jul 2004, Pierre Weis wrote: > > Your problem is thus that the function Debug.printf is not the right > > one (since it has not the right type :) > > Btw., since we are at it: I'd like to use my own printers depending on > a conditional, e.g.: > > let log level fmt = > if may_log level then > kfprintf ... > else > ??? > > If the given log level "level" does not allow logging the message > specified by "fmt", I just want to ignore the parameters provided together > with "fmt" - but how? Is there some (safe) trick, or do I have to write > my own Printf/Format-modules? I don't want to waste computation time > by unnecessarily converting format arguments to strings, which may be > very costly, e.g. when this would mean converting IPs to hostnames, etc. I don't know of any way to safely prevent the arguments of printf from being converted to string when interpreting the format. If you tolerate this effect, the problem is still a mere question of user's defined pretty-printer. Since you have a if then else, the ``???'' expression should have exactly the same type as the ``then kfprintf ...'' expression. Hence the simplest way to do so is to have another kfprintf invocation with the same format. Evidently you want to redirect the output of this invocation to /dev/null (I mean you do not want to see its output). The best way to do so is not to redefine a specialized version of printf, it is simply to define a specialized pretty printer that would behave as you want and then to specialize fprintf with it: let null_formatter = let null_out s idx len = () in let null_flush = ignore in Format.make_formatter null_out null_flush;; let may_log level = level > 1;; let log level fmt = if may_log level then fprintf err_formatter fmt else fprintf null_formatter fmt;; Hope this helps, Pierre Weis INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 22:20 ` Pierre Weis @ 2004-07-15 23:01 ` Markus Mottl 0 siblings, 0 replies; 56+ messages in thread From: Markus Mottl @ 2004-07-15 23:01 UTC (permalink / raw) To: Pierre Weis; +Cc: caml-list On Fri, 16 Jul 2004, Pierre Weis wrote: > I don't know of any way to safely prevent the arguments of printf from > being converted to string when interpreting the format. This would probably require some changes in the implementation of Printf/Format. > Since you have a if then else, the ``???'' expression should have > exactly the same type as the ``then kfprintf ...'' expression. Hence > the simplest way to do so is to have another kfprintf invocation with > the same format. Evidently you want to redirect the output of this > invocation to /dev/null (I mean you do not want to see its output). Not only this: I want to prevent any computations associated with generating output strings. > The best way to do so is not to redefine a specialized version of > printf, it is simply to define a specialized pretty printer that would > behave as you want and then to specialize fprintf with it: > > let null_formatter = > let null_out s idx len = () in > let null_flush = ignore in > Format.make_formatter null_out null_flush;; This would surely ignore any output, but "null_out" would still be called with superfluously generated strings. Anyway, the argument-eating function that makes use of "Obj.magic" works for me so my problem is solved. Regards, Markus -- Markus Mottl http://www.oefai.at/~markus markus@oefai.at ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [Caml-list] kprintf with user formatters 2004-07-15 0:17 ` Markus Mottl ` (2 preceding siblings ...) 2004-07-15 22:20 ` Pierre Weis @ 2004-07-16 16:17 ` james woodyatt 3 siblings, 0 replies; 56+ messages in thread From: james woodyatt @ 2004-07-16 16:17 UTC (permalink / raw) To: The Caml Trade On 14 Jul 2004, at 17:17, Markus Mottl wrote: > On Wed, 14 Jul 2004, Pierre Weis wrote: >> Your problem is thus that the function Debug.printf is not the right >> one (since it has not the right type :) > > Btw., since we are at it: I'd like to use my own printers depending on > a conditional, e.g.: > > let log level fmt = > if may_log level then > kfprintf ... > else > ??? > > If the given log level "level" does not allow logging the message > specified by "fmt", I just want to ignore the parameters provided > together > with "fmt" - but how? Is there some (safe) trick, or do I have to > write > my own Printf/Format-modules? I don't want to waste computation time > by unnecessarily converting format arguments to strings, which may be > very costly, e.g. when this would mean converting IPs to hostnames, > etc. The next release of my [Cf] library (due probably sometime this weekend) contains the foundation of a flexible diagnostic event journaling system, which is inspired by Log4j and various other similar systems. Using just the interface I'm almost ready to release now, the code would look like this: module J = Cf_journal if J.stdout#enabled `Info then J.stdout#info "this is an informational message (x=%d) x Note: because I plan to build this out to look a lot like Log4j, the format and its associated arguments are used to construct an event object and the event is sent to visit a list of archivers, each of which makes its own decision about how to write the events into their respective repositories. The [#enabled] method can be used to short-cut the call to [kprintf] embedded in the journal agent's logging methods. The example above is an example of using the built-in [stdout] basic agent, but that's a trivial example. For debugging messages, I simply made the [#debug] method return [true] so that it will be easily used inside [assert] expressions, like so: assert (J.stdout#debug "this is a debug message (x=%d)" x) I know this isn't what you want, but I don't see how there is a good way to get what you want. I generally like the idea of using the -noassert compile time option to decide whether to include the code for generating console debugging logs. -- j h woodyatt <jhw@wetware.com> markets are only free to the people who own them. ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 56+ messages in thread
end of thread, other threads:[~2004-07-28 12:31 UTC | newest] Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-06-30 16:32 [Caml-list] kprintf with user formatters Damien 2004-07-14 21:10 ` Pierre Weis 2004-07-15 0:17 ` Markus Mottl 2004-07-15 7:30 ` David MENTRE 2004-07-15 7:59 ` Jean-Christophe Filliatre 2004-07-15 23:35 ` henri dubois-ferriere 2004-07-15 7:39 ` Damien 2004-07-15 12:19 ` Markus Mottl 2004-07-15 12:42 ` Basile Starynkevitch [local] 2004-07-15 13:45 ` Markus Mottl 2004-07-15 14:22 ` Basile Starynkevitch [local] 2004-07-15 14:57 ` Markus Mottl 2004-07-16 6:47 ` Pierre Weis 2004-07-16 7:13 ` Jean-Christophe Filliatre 2004-07-16 7:23 ` henri dubois-ferriere 2004-07-16 7:44 ` Jean-Christophe Filliatre 2004-07-16 17:56 ` Markus Mottl 2004-07-19 9:17 ` Pierre Weis 2004-07-19 9:32 ` Jean-Christophe Filliatre 2004-07-16 7:21 ` henri dubois-ferriere 2004-07-16 17:44 ` Markus Mottl 2004-07-19 10:10 ` Pierre Weis 2004-07-19 10:43 ` Jon Harrop 2004-07-21 15:52 ` Pierre Weis 2004-07-21 17:43 ` lazyness in ocaml (was : [Caml-list] kprintf with user formatters) Daniel Bünzli 2004-07-22 16:28 ` Pierre Weis 2004-07-22 17:03 ` William Lovas 2004-07-22 23:00 ` skaller 2004-07-23 3:32 ` William Lovas 2004-07-28 7:26 ` Pierre Weis 2004-07-28 8:06 ` skaller 2004-07-28 8:29 ` Daniel Bünzli 2004-07-28 9:13 ` Pierre Weis 2004-07-28 9:36 ` skaller 2004-07-28 9:38 ` skaller 2004-07-28 10:17 ` Jason Smith 2004-07-28 12:31 ` skaller 2004-07-21 20:41 ` [Caml-list] kprintf with user formatters Jon Harrop 2004-07-22 15:39 ` Pierre Weis 2004-07-22 22:16 ` [Caml-list] lazy evaluation: [Was: kprintf with user formatters] skaller 2004-07-22 22:42 ` [Caml-list] kprintf with user formatters skaller 2004-07-22 8:05 ` [Caml-list] wait instruction lehalle@miriad 2004-07-22 8:40 ` Olivier Andrieu 2004-07-22 10:35 ` lehalle@miriad 2004-07-22 10:33 ` Vitaly Lugovsky 2004-07-16 6:17 ` [Caml-list] kprintf with user formatters Pierre Weis 2004-07-16 17:14 ` Markus Mottl 2004-07-19 10:00 ` Pierre Weis 2004-07-16 6:02 ` Pierre Weis 2004-07-16 8:42 ` Damien 2004-07-19 9:00 ` Pierre Weis 2004-07-16 16:52 ` Markus Mottl 2004-07-19 9:28 ` Pierre Weis 2004-07-15 22:20 ` Pierre Weis 2004-07-15 23:01 ` Markus Mottl 2004-07-16 16:17 ` james woodyatt
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox