Lazy evaluation

OF nospam at nospammington.com
Wed Jun 27 08:38:18 PDT 2007


Hey. I've been writing a bit on a "true" lazy evaluation (i.e. not evaluated until value is requested, but only evaluated once). A simple example of this can be achieved using a delegate, like so:

template Lazy(T)
{
	class Lazy
	{
		this(T delegate() exp)
		{
			mExp = exp;
		}

		T opCall()
		{
			if (!mEvaluated)
			{
				mValue = mExp();
				mEvaluated = true;
			}
			return mValue;
		}

	private:
		bool mEvaluated = false;
		final T delegate() mExp;
		T mValue;

	}
}

Which would work fine with Lazy!(int)( { return someExpr; } ), but it would be nice to be able to just use Lazy!(int)( someExpr ). However, it seems this can only be achieved using lazy function arguments, but problem is, if I use lazy function arguments, I can't really save it for later and do anything worthwhile with it.

Consider the additional constructor

this(lazy T lazyexp)
{
	mExp = { return lazyexp; };
}

which looks fine, but isn't (it crashed with Access Violation). It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates. Yet the article about lazy evaluation ( http://www.digitalmars.com/d/1.0/lazy-evaluation.html ) seems to indicate lazy is just syntetic sugar for delegates... but the behaviour is not like it at all. It doesn't seem to be able to convert a lazy expression to an delegate in any way (cast complains, the above, as said, crashes). Is there any way I've missed?

In addition, the above mentioned article states "So D takes it one small, but crucial, step further (suggested by Andrei Alexandrescu). Any expression can be implicitly converted to a delegate that returns either void or the type of the expression." which doesn't seem to be true either, or it would be enough with the first constructor that just uses the normal delegate syntax. Had this worked, it would have been fine for this case.

An other alternative I thought of was to save the lazy expression in the Lazy object instead of the delegate, but lazy seems to be completely restricted to function arguments. Is there any specific reason for this? I mean, "lazy int i = j++;" in, for example, a function isn't that much weirder. It's still just seems to be syntetic sugar for delegates, it should be able to work consistently with the behaviour of lazy for function arguments, should it not?

Any explanations or suggestions are welcome.

Slightly unrelated, is there anything in D corresponding to C++'s implicit cast operators (operator 'typename'(), e.g. operator int()) in D? I can't seem to find any... 



More information about the Digitalmars-d mailing list