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/

Reply via email to