www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - converting expression to delegate works only for variadic array?

reply Gopan <gggopan gmail.com> writes:
Hi,
I created a test application (test.d) to learn delegates.

import core.stdc.stdio;

void Multi (int delegate()[] args ...)
{
     foreach (exp; args)
	printf ("%d, ", exp() );
     printf ("\n");
}

void Single (int delegate() exp)
{
     printf ("%d\n", exp());
}

void main()
{
	int x = 5;
	Multi( {return 1;}, {return 2+x;} ); // outputs 1, 7 as expected.
	Multi( 1, 2+x); // same as above.  produces same output.
	Multi( 3+x ); //produces output 8.
	Single( { return 3+x; } ); //produces output 8
	Single( 3+x ); // COMPILATION ERROR pasted towards bottom.
         // Good. But why does Multi(2+x) not have this issue?
	
	int delegate() exp = { return 4+x; };
	printf("%d\n", exp() );
}
	
test.d(22): Error: function test.Single(int delegate() exp) is 
not callable using argument types (int)
test.d(22):        cannot pass argument 3 + x of type int to 
parameter int delegate() exp
make: *** [test.obj] Error 1

I am happy with the statement Single(3+x) producing this 
compilation error.

But why Multi(3+x) doesn't have this issue?  For that, it is 
allowed as per 'Section 19.16.3.4 Lazy Variadic Functions' of the 
article https://dlang.org/spec/function.html#closures.

What is the rationale behind not allowing it for the non-array 
signature?

Regards,
Gopan
Jun 01 2018
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/1/18 10:08 AM, Gopan wrote:
 Hi,
 I created a test application (test.d) to learn delegates.
 
 import core.stdc.stdio;
 
 void Multi (int delegate()[] args ...)
 {
      foreach (exp; args)
      printf ("%d, ", exp() );
      printf ("\n");
 }
 
 void Single (int delegate() exp)
 {
      printf ("%d\n", exp());
 }
 
 void main()
 {
      int x = 5;
      Multi( {return 1;}, {return 2+x;} ); // outputs 1, 7 as expected.
      Multi( 1, 2+x); // same as above.  produces same output.
      Multi( 3+x ); //produces output 8.
      Single( { return 3+x; } ); //produces output 8
      Single( 3+x ); // COMPILATION ERROR pasted towards bottom.
          // Good. But why does Multi(2+x) not have this issue?
 
      int delegate() exp = { return 4+x; };
      printf("%d\n", exp() );
 }
 
 test.d(22): Error: function test.Single(int delegate() exp) is not 
 callable using argument types (int)
 test.d(22):        cannot pass argument 3 + x of type int to parameter 
 int delegate() exp
 make: *** [test.obj] Error 1
 
 I am happy with the statement Single(3+x) producing this compilation error.
 
 But why Multi(3+x) doesn't have this issue?  For that, it is allowed as 
 per 'Section 19.16.3.4 Lazy Variadic Functions' of the article 
 https://dlang.org/spec/function.html#closures.
 
 What is the rationale behind not allowing it for the non-array signature?
These things were decided long ago, when D was just D1, and D2 didn't even exist. I think the rationale might go like this: 1. We have a lazy parameter, lazy int, which translates into a delegate automatically. 2. Cool, we need a way to do this with variadics. But what does lazy int[]... mean? Does it mean an array that's lazily calculated, or does it mean an array of lazily calculated parameters? 3. lazy int[]... was decided to mean a lazily calculated int array (the whole array is created whenever it is used). 4. int delegate()[]... was decided to mean an array of lazily passed ints. IMO, lazy X and X delegate() should be interchangeable API-wise and exactly the same. You should be able to call either one with an X or a delegate. This makes the most sense and is the most useful. -Steve
Jun 01 2018