November 01, 2010
Hello,

why is the following code illegal?


  import std.stdio;

  void delegate() fun;

  void capture(lazy void f) {
    fun = &f;
  }

  void main() {
    capture(writeln("hello"));
    fun();
  }


It says "Error: lazy variables cannot be lvalues", pointing to the "fun = &f" line.

It can be worked around by rewriting it like this:

void capture(lazy void f) {
  fun = delegate void() { f(); };
}

So it's not big deal, just a minor inconvenience. But still, why is it illegal? According to the docs (http://www.digitalmars.com/d/2.0/lazy-evaluation.html), lazy expressions are implicitly converted to delegates, so it seems to me that it should work.

adam.
November 01, 2010
On 01/11/2010 15:57, Adam Cigánek wrote:
<snip>
>    void capture(lazy void f) {
>      fun =&f;
>    }
<snip>
> It says "Error: lazy variables cannot be lvalues", pointing to the
> "fun =&f" line.

Because f doesn't have an address.  It's just an expression that's evaluated where it's used.  It's true that the function in which the compiler wraps f has an address, but that isn't the same.

> It can be worked around by rewriting it like this:
>
> void capture(lazy void f) {
>    fun = delegate void() { f(); };
> }
>
> So it's not big deal, just a minor inconvenience. But still, why is it
> illegal? According to the docs
> (http://www.digitalmars.com/d/2.0/lazy-evaluation.html), lazy
> expressions are implicitly converted to delegates, so it seems to me
> that it should work.

This is inaccurate or at least badly worded.  What's really meant is that the compiler converts the lazy expression to a delegate. Unfortunately, there's no way at the moment to extract that delegate, though I do wish D explicitly supported & as a way of doing it.

There's a workaround: declaring the function instead as

    void capture(void delegate()[1] f...)

which is the special case given on
http://www.digitalmars.com/d/1.0/function.html
under "Lazy Variadic Functions".

Stewart.