On 2009-12-06 10:44:17 -0500, Andrei Alexandrescu
<[email protected]> said:
Tim Matthews wrote:
Andrei Alexandrescu wrote:
Should we sack lazy? I'd like it to have a reasonable replacement.
Ideas are welcome!
Andrei
According to the doc page:
http://www.digitalmars.com/d/2.0/lazy-evaluation.html
you (and/or Tomasz Stachowiak) were the one who suggested it in the
first place. How'd it go for you? :)
Well the story is, I suggested something very different, namely
automatic conversion of expressions to delegates, i.e.:
void fun(int delegate() dg) { ... }
int a;
fun(a += 5); // works, same as fun({ a += 5; });
I am not sure about how good that idea is, but anyway on top of it
Tomasz suggested defining a storage class for that, which (1) takes
matters to a completely place, (2) marks a sharp decline in the quality
of the feature. I protested the addition of "lazy" very strongly in a
subsequent post. Since I was relatively new in the newsgroup and the
rant bordered on an ad hominem attack against Tomasz, it earned me a
good amount of negative goodwill (and for good reasons). If I remember
correctly, the flamewar that ensued in my leaving the newsgroup for a
good while. I'm very glad the atmosphere has improved so much since -
back then it was often some sort of a turf war.
Anyhow, if we leave the feature as an implicit conversion expression ->
delegate or function, I think the whole thing is sound (contingent on
probably taking care of a couple of corner cases). The remaining
problem is that fun(gun()) does not always evaluate gun(), even though
the reader who is unaware or forgot about the conversion thinks
otherwise. If we require fun({gun();}), the notation is more awkward
but also clarifies to the reader what's happening.
My take is this: since assert() establishes a precedent, I'd hate that
to be magic inaccessible to mere mortals. Functions like enforce() and
logging frameworks can make good use of the feature.
That's what I'd do too.
But I think we could improve lazy by splitting it in two. The first
would work as it does today, allowing things like enforce(). The second
could be less intrusive by having no semantic implications for the
caller. The idea is simple: force purity on it. This way, the caller
doesn't have to think about whether or not an argument is a lazy one or
not. Suggested syntax:
void logIfFalse(bool condition, pure lazy string message);
logIfFalse(i == 1, createMessage());
If the expression "createMessage()" is pure, then it'll be evaluated
lazily. Otherwise it should be evaluated in advance (like normal
parameters) and a delegate returning the result should be given to the
function.
This would make it mostly a cross-function manual optimization
mechanism. The called function can assume its "pure lazy" delegate is
pure and optimize things accordingly. If you have a couple of functions
passing themselves a "pure lazy" argument like that, a good optimizer
could make sure it is never is evaluated more than once even across
function boundaries.
--
Michel Fortin
[email protected]
http://michelf.com/