View mode: basic / threaded / horizontal-split · Log in · Help
January 05, 2012
An issue with lazy delegates
import std.stdio;

void test(T)(lazy T dg)
{
   test2(dg);
}

void test2(T)(lazy T dg)
{
   dg();    // nothing happens
   dg()();  // have to use double-invocation instead
}

void main()
{
   test({ writeln("test"); });
}

Do you think it would be possible for the compiler to avoid wrapping
delegates into another delegate? I'm having this problem with this
sort of template:

import std.conv;
import std.string;

auto onFailThrow(E, T)(lazy T dg)
{
   try
   {
       static if (is(ReturnType!T == void))
           dg();
       else
           return dg();
   }
   catch (Exception ex)
   {
       throw new E(ex.msg);
   }
}

void main()
{
   string x = "x";
   string y = "y";
   onFailThrow!Exception({ to!int(x); });
   onFailThrow!Exception(to!int(y));
}

The first call doesn't do anything because the delegate is wrapped
inside of another delegate. I want this template to be versatile
enough to be used by both lazy expressions and delegate literals, but
I don't know how.

If I write the same template but with "lazy" stripped off I'll have
conflicting templates, but I don't know how I would write constraints
to separate the two. Any ideas?
January 07, 2012
Re: An issue with lazy delegates
On 5/01/12 5:26 AM, Andrej Mitrovic wrote:
> The first call doesn't do anything because the delegate is wrapped
> inside of another delegate. I want this template to be versatile
> enough to be used by both lazy expressions and delegate literals, but
> I don't know how.

void test(T)(lazy T dg)
{
    static if (is(T == delegate))
        dg()();
    else
        dg();
}

void main()
{
    test( writeln("a") );
    test( { writeln("b"); } );
}
January 07, 2012
Re: An issue with lazy delegates
Hah, I never thought of using that check. Thanks.
January 09, 2012
Re: An issue with lazy delegates
On 05/01/2012 05:26, Andrej Mitrovic wrote:
<snip>
> The first call doesn't do anything because the delegate is wrapped
> inside of another delegate. I want this template to be versatile
> enough to be used by both lazy expressions and delegate literals, but
> I don't know how.
<snip>

If you have a delegate you want to use as a lazy expression, you can make the lazy 
argument a call to it

    onFailThrow!Exception({ to!int(x); }());

Of course, Peter's solution enables you to omit the () and just pass the delegate in, but 
it does mean that you can't lazily evaluate an expression to a delegate, unless you wrap 
it in a delegate literal.

Stewart.
Top | Discussion index | About this forum | D home