lazy evaluation

Pierre Habouzit pierre.habouzit at m4x.org
Fri Jun 1 12:35:03 PDT 2007


  The behaviour of lazy in wrt lazy arguments, and it did not worked
like I expected. let's take the following code as an example:

--------------------------------------------
import std.stdio;

int foo() {
    static int i = 0;
    return i++;
}

void baz(lazy int i)
{
    writefln("baz %d", i());
}

void bar(lazy int i) {
    baz(i);
    writefln("bar %d", i());
}

int main()
{
    bar(foo());
    return 0;
}
--------------------------------------------

(small remark, I regret the very handy __func__ variable from C99
here...)

  if you compile that code, the output will be :

baz 0
bar 1

  Whereas I would have expected 0 and ... 0. I know the code I show is
well, nasty as the lazy expression has a side effect, but it was just a
way for me to test if lazy expressions were memoized (what I really
expected) or not. It appears they are not, and well, that's not good.

  On digitalmars website we can read that lazy can be used to avoid
computation. Let's say for logging purposes. Good example: the
programmer could have two optional backend for logging, e.g. on stderr
and in the syslog. and if he does not uses an intermediate variable to
store the lazy epxressions, it will be evaluated two times. Of course
doing so is completely defeating the very purpose of lazy.

  There is another language that has some kind of lazy expression
support, not only for function parameters but as a type attribute,
python users would say decorators, it's Ocaml. See how it works:

--------------------------------------------
$ ocaml
        Objective Caml version 3.09.2

# let a = ref 0;;
val a : int ref = {contents = 0}
# let counter () = let result = !a in a := !a + 1; result;;
val counter : unit -> int = <fun>
# counter();;                 
- : int = 0
# counter ();;
- : int = 1
# let laz = lazy (counter ());;
val laz : int lazy_t = <lazy>
# Lazy.force laz;;
- : int = 2
# Lazy.force laz;;
- : int = 2
--------------------------------------------

  lazy types are supported through the Lazy module, and forcing the
evaluation of a lazy type is done through Lazy.force expr rather than
expr() like in D. Though, like you can see, once forced, the lazy
expression sees its value memoized.

  I'm wondering:
  * why lazy types in D don't work like that for lazy parameters,
    because it's really what makes sense and is the most predictible
    behaviour ;
  * also why it's not a generic type attribute either and only used as a
    function parameter. Not knowing the implementation gory details, I
    don't know if it makes sense at all anyway.


-- 
·O·  Pierre Habouzit
··O                                                madcoder at debian.org
OOO                                                http://www.madism.org



More information about the Digitalmars-d mailing list