Thread overview
What is the difference between "delegate()" and "lazy delegate()" ?
Jan 02, 2021
Marcone
Jan 02, 2021
frame
Jan 02, 2021
Ali Çehreli
January 02, 2021
Why "lazy delegate()" need two parentheses to execute function?
January 02, 2021
On Saturday, 2 January 2021 at 12:29:43 UTC, Marcone wrote:
> Why "lazy delegate()" need two parentheses to execute function?

AFAIK is 'lazy' some kind of delegate storage class which accept an expression to execute. The reason you can actually use the parameter without "()" is just CTFE sugar which calls it automatically on use.

On the other hand, if you supply a 'lazy delegate()' the compiler does not know to call only the lazy expression or the delegate itself.


January 02, 2021
On 1/2/21 4:29 AM, Marcone wrote:
> Why "lazy delegate()" need two parentheses to execute function?

lazy automatically makes a delegate that returns the type of the parameter:

void bar(lazy int i) {
  writeln(i);  // i is a delegate called automatically
}

Strangely, the delegateness leaks out and i() works as well:

  writeln(i());  // WAT?

I agree with you that double parenthesis is strange for a lazy delegate but the fact above explains to me what is happening: The first set is for lazy's delegate to get the actual delegate, and the second set is used for calling the actual delegate.

I agree that it feels wrong that d(3) is not allowed below even though 'i' alone is allowed above. I vaguely remember issues around delegates where it wouldn't be clear whether one is referring to the delegate itself with 'd' or whether calling the delegate as d() but without the parenthesis.

Yeah, that's it: If we were allowed to call delegates without the optional parenthesis, we would never be allowed to refer to a delegate itself:

  typeof(d)    // <-- Is that the type of the delegate or what it returns?

So, the double parenthesis are needed for the fact that delegates cannot be called without optional parenthesis. (I think. :) )

Here is a program that I played with before writing this:

import std.stdio;
import core.thread;
import std.random;

void foo(lazy int delegate(int) d) {
  if (dice(50, 50)) {
    writeln("Using the delegate");
    d()(3);    // d(3) should work as well
  }
}

int delegate(int) delegateMaker(int multiplier) {
  writeln("Waiting for expensive delegate making operation...");
  Thread.sleep(2.seconds);

  return (int i) {
    writeln("Delegate called");
    return multiplier * i;
  };
}

void main(string[] args) {
  foo(delegateMaker(2));
}

Ali