June 03, 2017
Hello,

I've been playing around with the idea of lazy evaluation for function arguments [1] and I really like how it can be used to simplify deep nested loops operating on structured data.

It also seems that you can get quite far without invoking the GC using the `scope` keyword. I’ve been experimenting on some code and I’ve reached an interesting situation. A similar thing has been filed as a bug [2] but it seems that `scope` was not available in its current form back then.

Here’s some code to present the case.

@nogc lazy evaluation using scoped delegates:

Compiles fine in DMD v2.074.0,

import std.stdio;
int DoTimes(int count, scope int delegate() @nogc nothrow Dg) @nogc nothrow {
    foreach (i ; 0 .. count)
        Dg();

    return 1;
}

int DoAgain() @nogc nothrow {
    int x = 0, y = 10;
    return DoTimes(2, { return DoTimes(4, { return printf("x:%d, y:%d\n", x++, y++); }); } );
}

void foo() @nogc nothrow {
    DoTimes(2, { return DoTimes(4, { return DoAgain(); }); } );
}

void main(string[] args) {
  auto Lambda = () => foo();
  Lambda();
}

@nogc lazy evaluation using `lazy` arguments:

Exits with
Error: @nogc function 'app.DoTimes' cannot call non-@nogc delegate 'Dg' in DMD v2.074.0.

import std.stdio;
int DoTimes(int count, scope lazy int Dg) @nogc nothrow
{
    foreach (i ; 0 .. count)
        Dg();

    return 1;
}

int DoAgain() @nogc nothrow {
    int x = 0, y = 10;
    return DoTimes(2, DoTimes(4, printf("x:%d, y:%d\n", x++, y++) ) );
}

void foo() @nogc nothrow {
    DoTimes(2, DoTimes(4, DoAgain() ) );
}

void main(string[] args) {

  auto Lambda = () => foo();
  Lambda();

}

typeof(Dg) returns `int` and not some kind of delegate. It seems that the conversion happens at a later stage and so we do not get the expected type.

In any case, do you think that `scope` should allow for such code to compile? Since you can get the desired result using the verbose version, I think you should also be able to using the `lazy` construct.

Thank you for any suggestions.

[1] https://dlang.org/lazy-evaluation.html
[2] https://issues.dlang.org/show_bug.cgi?id=12664

June 03, 2017
On Saturday, 3 June 2017 at 14:34:41 UTC, Nick Vitsas wrote:
> In any case, do you think that `scope` should allow for such code to compile? Since you can get the desired result using the verbose version, I think you should also be able to using the `lazy` construct.

I think so. There's even a pull request that modifies lazy so that other functions attributes (incl. @nogc) are inferred.

https://github.com/dlang/dmd/pull/6348

The problem is that it seems to be out of scope / interest now (last activity was on 24 of Feb), almost 6 months.