caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Re: log function without evaluate arguments
  2007-11-06 17:05 log function without evaluate arguments tmp123
@ 2007-11-06 16:57 ` Sylvain Le Gall
  2007-11-06 18:25 ` [Caml-list] " Nicolas Pouillard
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 12+ messages in thread
From: Sylvain Le Gall @ 2007-11-06 16:57 UTC (permalink / raw)
  To: caml-list

On 06-11-2007, tmp123 <tmp123@menta.net> wrote:
> Hello,
>
> In order to implement a function that prints log messages only, by
> example, if a boolean flag is true, and does nothing elsewhere, I've
> been reading the (long) post sequence "kprintf with user formatters"
> (2004 Jun 30).
>
> In this context, "does nothing" means not convert parameters to text nor
> evaluate them.
>
> If my understanting of the reading has been correct, one of the best
> options seems to be something like (in camlp4r revised syntax, I'm more
> used to it):
>
> value log_flag = ref False;
>
> value log e =
>   if log_flag.val
>   then
>     Lazy.force e
>   else ();
>
> and the callers must include lines like:
>
> log (lazy (Printf.printf "%d" (sum 1 3)));
>
> Please, is this a good way? Some sugestions to made it better in
> performance or syntax?
>
> Thanks a lot.
>

I am used to :
 value log e =
   if log_flag.val then
     e ()
   else 
     ();

avec log (fun () -> (Printf.printf "%d" (sum 1 3)))

But the enhancement is minor.

Regards,
Sylvain Le Gall


^ permalink raw reply	[flat|nested] 12+ messages in thread

* log function without evaluate arguments
@ 2007-11-06 17:05 tmp123
  2007-11-06 16:57 ` Sylvain Le Gall
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: tmp123 @ 2007-11-06 17:05 UTC (permalink / raw)
  To: caml-list

Hello,

In order to implement a function that prints log messages only, by
example, if a boolean flag is true, and does nothing elsewhere, I've
been reading the (long) post sequence "kprintf with user formatters"
(2004 Jun 30).

In this context, "does nothing" means not convert parameters to text nor
evaluate them.

If my understanting of the reading has been correct, one of the best
options seems to be something like (in camlp4r revised syntax, I'm more
used to it):

value log_flag = ref False;

value log e =
  if log_flag.val
  then
    Lazy.force e
  else ();

and the callers must include lines like:

log (lazy (Printf.printf "%d" (sum 1 3)));

Please, is this a good way? Some sugestions to made it better in
performance or syntax?

Thanks a lot.





^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-06 17:05 log function without evaluate arguments tmp123
  2007-11-06 16:57 ` Sylvain Le Gall
@ 2007-11-06 18:25 ` Nicolas Pouillard
  2007-11-06 18:40   ` Till Varoquaux
  2007-11-07  3:40 ` Christopher L Conway
       [not found] ` <4a051d930711061938u25836a85ud28c610312e5896f@mail.gmail.com>
  3 siblings, 1 reply; 12+ messages in thread
From: Nicolas Pouillard @ 2007-11-06 18:25 UTC (permalink / raw)
  To: tmp123; +Cc: caml-list

Excerpts from tmp123's message of Tue Nov 06 18:05:48 +0100 2007:
> Hello,
> 
> In order to implement a function that prints log messages only, by
> example, if a boolean flag is true, and does nothing elsewhere, I've
> been reading the (long) post sequence "kprintf with user formatters"
> (2004 Jun 30).
> 
> In this context, "does nothing" means not convert parameters to text nor
> evaluate them.

Have a look to the Printf.ifprintf [1] function, it does exactly what you want.

Regards,

[1]:
val ifprintf : 'a -> ('b, 'a, unit) format -> 'b
(** Same as {!Printf.fprintf}, but does not print anything.
    Useful to ignore some material when conditionally printing. *)

-- 
Nicolas Pouillard aka Ertai


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-06 18:25 ` [Caml-list] " Nicolas Pouillard
@ 2007-11-06 18:40   ` Till Varoquaux
  2007-11-06 18:49     ` Brian Hurt
  2007-11-07 10:21     ` Nicolas Pouillard
  0 siblings, 2 replies; 12+ messages in thread
From: Till Varoquaux @ 2007-11-06 18:40 UTC (permalink / raw)
  To: Nicolas Pouillard; +Cc: tmp123, caml-list

On 11/6/07, Nicolas Pouillard <nicolas.pouillard@gmail.com> wrote:
> Excerpts from tmp123's message of Tue Nov 06 18:05:48 +0100 2007:
> > Hello,
> >
> > In order to implement a function that prints log messages only, by
> > example, if a boolean flag is true, and does nothing elsewhere, I've
> > been reading the (long) post sequence "kprintf with user formatters"
> > (2004 Jun 30).
> >
> > In this context, "does nothing" means not convert parameters to text nor
> > evaluate them.
>
> Have a look to the Printf.ifprintf [1] function, it does exactly what you want.
>
> Regards,
>
Actually it doesn't:

   log (lazy (Printf.printf "%s" (awfully_long_computation ())))

when log_val is false (or sylvain's solution, which I prefer), will
not behave like

   Printf.ifprinf "%s" (awfully_long_computation ())

(it won't evaluate its arguments).

Till
-- 
http://till-varoquaux.blogspot.com/


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-06 18:40   ` Till Varoquaux
@ 2007-11-06 18:49     ` Brian Hurt
  2007-11-07  3:39       ` Christopher L Conway
  2007-11-07 10:21     ` Nicolas Pouillard
  1 sibling, 1 reply; 12+ messages in thread
From: Brian Hurt @ 2007-11-06 18:49 UTC (permalink / raw)
  To: Till Varoquaux; +Cc: Nicolas Pouillard, tmp123, caml-list

[-- Attachment #1: Type: text/plain, Size: 948 bytes --]

Till Varoquaux wrote:

>Actually it doesn't:
>
>   log (lazy (Printf.printf "%s" (awfully_long_computation ())))
>
>when log_val is false (or sylvain's solution, which I prefer), will
>not behave like
>
>   Printf.ifprinf "%s" (awfully_long_computation ())
>
>(it won't evaluate its arguments).
>
>Till
>  
>
IMHO: evaluating the arguments of your log statement will avoid some 
really ugly heisenbugs- what if awfully_long_computation performs I/O or 
otherwise has side effects?.  Note that having side-effects in your 
arguments to the log statements is a really bad idea, but people will do 
it, and finding where they do it is non-trivial.

Also, creating a lazy thunk in Ocaml is expensive (like 140+ clock 
cycles), while passing an argument into a function is cheap- and the 
common case will be that the argument won't need to be evaluated, just 
passed in.

Translation: don't try to be too clever to avoid evaluating arguments.

Brian



[-- Attachment #2: Type: text/html, Size: 1334 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-06 18:49     ` Brian Hurt
@ 2007-11-07  3:39       ` Christopher L Conway
  2007-11-07  4:00         ` Erik de Castro Lopo
  0 siblings, 1 reply; 12+ messages in thread
From: Christopher L Conway @ 2007-11-07  3:39 UTC (permalink / raw)
  To: Brian Hurt; +Cc: caml-list

On 11/6/07, Brian Hurt <bhurt@janestcapital.com> wrote:
>  Also, creating a lazy thunk in Ocaml is expensive (like 140+ clock cycles),
> while passing an argument into a function is cheap- and the common case will
> be that the argument won't need to be evaluated, just passed in.

What does this mean? Did OCaml become non-strict while I wasn't looking?

Chris


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-06 17:05 log function without evaluate arguments tmp123
  2007-11-06 16:57 ` Sylvain Le Gall
  2007-11-06 18:25 ` [Caml-list] " Nicolas Pouillard
@ 2007-11-07  3:40 ` Christopher L Conway
       [not found] ` <4a051d930711061938u25836a85ud28c610312e5896f@mail.gmail.com>
  3 siblings, 0 replies; 12+ messages in thread
From: Christopher L Conway @ 2007-11-07  3:40 UTC (permalink / raw)
  To: caml-list

If you're using OCaml version <= 3.09, check out pa_log
(http://www.cs.nyu.edu/~cconway/tools/index.html). I wrote it for
exactly this purpose.

Even if you're using 3.10, you might want to check it out. It's a
really simple extension and updating it might be a good excuse to
learn the new camlp4.

Regards,
Chris

On 11/6/07, tmp123 <tmp123@menta.net> wrote:
> Hello,
>
> In order to implement a function that prints log messages only, by
> example, if a boolean flag is true, and does nothing elsewhere, I've
> been reading the (long) post sequence "kprintf with user formatters"
> (2004 Jun 30).
>
> In this context, "does nothing" means not convert parameters to text nor
> evaluate them.
>
> If my understanting of the reading has been correct, one of the best
> options seems to be something like (in camlp4r revised syntax, I'm more
> used to it):
>
> value log_flag = ref False;
>
> value log e =
>   if log_flag.val
>   then
>     Lazy.force e
>   else ();
>
> and the callers must include lines like:
>
> log (lazy (Printf.printf "%d" (sum 1 3)));
>
> Please, is this a good way? Some sugestions to made it better in
> performance or syntax?
>
> Thanks a lot.
>
>
>
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-07  3:39       ` Christopher L Conway
@ 2007-11-07  4:00         ` Erik de Castro Lopo
  2007-11-07  4:10           ` Christopher L Conway
  0 siblings, 1 reply; 12+ messages in thread
From: Erik de Castro Lopo @ 2007-11-07  4:00 UTC (permalink / raw)
  To: caml-list

Christopher L Conway wrote:

> On 11/6/07, Brian Hurt <bhurt@janestcapital.com> wrote:
> >  Also, creating a lazy thunk in Ocaml is expensive (like 140+ clock cycles),
> > while passing an argument into a function is cheap- and the common case will
> > be that the argument won't need to be evaluated, just passed in.
> 
> What does this mean? Did OCaml become non-strict while I wasn't looking?

Ocaml is strict by default and optionally lazy.

The code being discussed was this:

    log (lazy (Printf.printf "%s" (awfully_long_computation ())))

where everything inside

    (lazy X)

is lazy evaluated.

Erik
-- 
-----------------------------------------------------------------
Erik de Castro Lopo
-----------------------------------------------------------------
"I'd rather not work with people who aren't careful. It's darwinism
in software development." -- Linus Torvalds on the linux-kernel list


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-07  4:00         ` Erik de Castro Lopo
@ 2007-11-07  4:10           ` Christopher L Conway
  2007-11-07 13:42             ` Brian Hurt
  0 siblings, 1 reply; 12+ messages in thread
From: Christopher L Conway @ 2007-11-07  4:10 UTC (permalink / raw)
  To: caml-list

On 11/6/07, Erik de Castro Lopo <mle+ocaml@mega-nerd.com> wrote:
> Christopher L Conway wrote:
>
> > On 11/6/07, Brian Hurt <bhurt@janestcapital.com> wrote:
> > >  Also, creating a lazy thunk in Ocaml is expensive (like 140+ clock cycles),
> > > while passing an argument into a function is cheap- and the common case will
> > > be that the argument won't need to be evaluated, just passed in.
> >
> > What does this mean? Did OCaml become non-strict while I wasn't looking?
>
> Ocaml is strict by default and optionally lazy.
>
> The code being discussed was this:
>
>     log (lazy (Printf.printf "%s" (awfully_long_computation ())))
>
> where everything inside
>
>     (lazy X)
>
> is lazy evaluated.

Yes, of course. But, if I understand correctly, Brian was arguing in favor of

   Printf.ifprinf "%s" (awfully_long_computation ())

and claiming that it was potentially more efficient than the lazy version.

Chris


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-06 18:40   ` Till Varoquaux
  2007-11-06 18:49     ` Brian Hurt
@ 2007-11-07 10:21     ` Nicolas Pouillard
  1 sibling, 0 replies; 12+ messages in thread
From: Nicolas Pouillard @ 2007-11-07 10:21 UTC (permalink / raw)
  To: till.varoquaux; +Cc: tmp123, caml-list

Excerpts from till.varoquaux's message of Tue Nov 06 19:40:19 +0100 2007:
> On 11/6/07, Nicolas Pouillard <nicolas.pouillard@gmail.com> wrote:
> > Excerpts from tmp123's message of Tue Nov 06 18:05:48 +0100 2007:
> > > Hello,
> > >
> > > In order to implement a function that prints log messages only, by
> > > example, if a boolean flag is true, and does nothing elsewhere, I've
> > > been reading the (long) post sequence "kprintf with user formatters"
> > > (2004 Jun 30).
> > >
> > > In this context, "does nothing" means not convert parameters to text nor
> > > evaluate them.
> >
> > Have a look to the Printf.ifprintf [1] function, it does exactly what you want.
> >
> > Regards,
> >
> Actually it doesn't:
> 
>    log (lazy (Printf.printf "%s" (awfully_long_computation ())))
> 
> when log_val is false (or sylvain's solution, which I prefer), will
> not behave like
> 
>    Printf.ifprinf "%s" (awfully_long_computation ())
> 
> (it won't evaluate its arguments).

Of course but you should use %a:

let log fmt = if debug_mode then Printf.fprintf fmt else Printf.ifprintf fmt;;

let awfully_long_computation' oc () = Printf.fprintf "%s" (awfully_long_computation ());;

log "%a" awfully_long_computation' ()

Regards,

-- 
Nicolas Pouillard aka Ertai


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
       [not found] ` <4a051d930711061938u25836a85ud28c610312e5896f@mail.gmail.com>
@ 2007-11-07 10:31   ` tmp123
  0 siblings, 0 replies; 12+ messages in thread
From: tmp123 @ 2007-11-07 10:31 UTC (permalink / raw)
  To: caml-list

Hello,

Thanks a lot to everybody for your help.

I've been testing the different proposals. I must recognize I've not yet 
reviewed the proposed library, it is next step.

The four methods tested are: lazy, fun, ifprint, and fun moving the "if" 
to the caller (see full listing and results at the end of the post). Two 
test has been done for each one: when parameter is an integer constant 
and when parameter is the result of a funcion call who mades an addition.

The conclusion seems: defining that "lazy" method needs 1 unit of time, 
proposal using "fun" instead of lazy needs 0.8, and the version 
"ifprintf" needs 16. Proposal moving the "if" needs 0.7.

Thus, if no error has been done, fun is the fastest option, lazy is near.

Another point is the posibility of, using a camlp4 syntax extension, to 
introduce a few of sugar. Something like expand:

from: log "some=%d\" 14;
to: logint ( fun () -> Printf.printf "some=%d\n" 14);
or to: if log_active.val then logint ( fun() -> Printf.printf 
"some=%d\n" 14) else ();

Thanks again to everybody.

Full listing and results:

value log_active = ref False;

value log1 exp =
  if log_active.val
  then
    Lazy.force exp
  else ();

value log2 exp =
  if log_active.val
  then
    exp()
  else ();

value log3 fmt =
  if log_active.val
  then
    Printf.printf fmt
  else
    Printf.ifprintf stderr fmt;

value log4 exp = exp ();




value suma a b =
(
  a+b;
);

value some = ref 14;

value test1 () =
  log1 (lazy (Printf.printf "%d" (suma some.val 3)));

value test2 () =
  log2 ( fun () -> Printf.printf "%d" (suma some.val 3));

value test3 () =
  log3 "%d" (suma some.val 3);

value test4 () =
  if log_active.val then log4 ( fun () -> Printf.printf "%d" (suma 
some.val 3))
                    else ();

value testb1 () =
  log1 (lazy (Printf.printf "%d" 3));

value testb2 () =
  log2 ( fun () -> Printf.printf "%d" 3);

value testb3 () =
  log3 "%d" 3;

value testb4 () =
  if log_active.val then log4 ( fun () -> Printf.printf "%d" 3)
                    else ();




value loop f =
(
    let t=Unix.times() in
    Printf.printf "%f %f %f\n" (Unix.gettimeofday())
                             t.Unix.tms_utime t.Unix.tms_stime;

    for i = 0 to 1000 do
    for j = 0 to 1000000 do
      f ();
    done;
    done;

    let t=Unix.times() in
    Printf.printf "%f %f %f\n" (Unix.gettimeofday())
                             t.Unix.tms_utime t.Unix.tms_stime;
);

value main () =
(
  Printf.printf "test1\n";
  loop test1;

  Printf.printf "test2\n";
  loop test2;

  Printf.printf "test3\n";
  loop test3;

  Printf.printf "test4\n";
  loop test4;

  Printf.printf "\n";

  Printf.printf "testb1\n";
  loop testb1;

  Printf.printf "testb2\n";
  loop testb2;

  Printf.printf "testb3\n";
  loop testb3;

  Printf.printf "testb4\n";
  loop testb4;

);

main();


Results:

test1
1194426404.657406 0.015000 0.000000
1194426414.136406 9.453000 0.000000
test2
1194426414.137406 9.468000 0.000000
1194426422.147406 17.453000 0.000000
test3
1194426422.147406 17.453000 0.000000
1194426593.308406 188.515000 0.000000
test4
1194426593.308406 188.515000 0.000000
1194426599.964406 195.156000 0.000000

testb1
1194426599.964406 195.156000 0.000000
1194426609.408406 204.609000 0.000000
testb2
1194426609.408406 204.609000 0.000000
1194426617.378406 212.578000 0.000000
testb3
1194426617.378406 212.578000 0.000000
1194426790.412406 385.484000 0.000000
testb4
1194426790.412406 385.484000 0.000000
1194426797.060406 392.125000 0.000000


-------------


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] log function without evaluate arguments
  2007-11-07  4:10           ` Christopher L Conway
@ 2007-11-07 13:42             ` Brian Hurt
  0 siblings, 0 replies; 12+ messages in thread
From: Brian Hurt @ 2007-11-07 13:42 UTC (permalink / raw)
  To: Christopher L Conway; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 1308 bytes --]

Christopher L Conway wrote:

>On 11/6/07, Erik de Castro Lopo <mle+ocaml@mega-nerd.com> wrote:
>  
>
>>Christopher L Conway wrote:
>>
>>    
>>
>>>On 11/6/07, Brian Hurt <bhurt@janestcapital.com> wrote:
>>>      
>>>
>>>> Also, creating a lazy thunk in Ocaml is expensive (like 140+ clock cycles),
>>>>while passing an argument into a function is cheap- and the common case will
>>>>be that the argument won't need to be evaluated, just passed in.
>>>>        
>>>>
>>>What does this mean? Did OCaml become non-strict while I wasn't looking?
>>>      
>>>
>>Ocaml is strict by default and optionally lazy.
>>
>>The code being discussed was this:
>>
>>    log (lazy (Printf.printf "%s" (awfully_long_computation ())))
>>
>>where everything inside
>>
>>    (lazy X)
>>
>>is lazy evaluated.
>>    
>>
>
>Yes, of course. But, if I understand correctly, Brian was arguing in favor of
>
>   Printf.ifprinf "%s" (awfully_long_computation ())
>
>and claiming that it was potentially more efficient than the lazy version.
>
>  
>
No, I was arguing that:

Printf.ifprintf "%s" "foo"

was more efficient, and was a much more common case.

I was also arguing that:

Printf.ifprintf "%s" (awfully_long_computation ())

was more likely to be correct, especially if awfully_long_computation 
includes side effects.

Brian


[-- Attachment #2: Type: text/html, Size: 2094 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2007-11-07 13:43 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-06 17:05 log function without evaluate arguments tmp123
2007-11-06 16:57 ` Sylvain Le Gall
2007-11-06 18:25 ` [Caml-list] " Nicolas Pouillard
2007-11-06 18:40   ` Till Varoquaux
2007-11-06 18:49     ` Brian Hurt
2007-11-07  3:39       ` Christopher L Conway
2007-11-07  4:00         ` Erik de Castro Lopo
2007-11-07  4:10           ` Christopher L Conway
2007-11-07 13:42             ` Brian Hurt
2007-11-07 10:21     ` Nicolas Pouillard
2007-11-07  3:40 ` Christopher L Conway
     [not found] ` <4a051d930711061938u25836a85ud28c610312e5896f@mail.gmail.com>
2007-11-07 10:31   ` tmp123

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).