www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - closures + struct: Error: forward reference to inferred return type

reply ddcovery <antoniocabreraperez gmail.com> writes:
In this example, I try to use D Voldemore (fantastic) 
functionallity to implement a pattern usually used in javascript.

Basically, a function closure represents the state, and the 
methods to access this state are returned in the form of union 
(union has not state itself).

void main(){
   assert(number(10).next.value==11 );
   assert(zero()==number(0) );
   assert(zero()==number(1).previous );
   auto ten = number(10);
   auto nine = ten.previous;
   assert(nine == number(9));
}

auto number(int _value=0){
   struct Number {
     int value() {
       return _value;
     };
     Number next() {
       return number(_value+1);
     };
     Number previous(){
       return number(_value-1);
     };
     int opCmp(Number other){
       return _value - other.value;
     };
   }

   return Number();
}

auto zero() {
   return number(0);
}

Problem is that Union methods needs to call it's containing 
function and compiler doesn't accept it:

main.d(16): Error: forward reference to inferred return type of 
function call number(_value + 1)
main.d(19): Error: forward reference to inferred return type of 
function call number(_value - 1)

I know there is another ways to solve this problem easily 
(without closures), but I was really curious about if it was 
possible.
Dec 14 2020
parent reply ddcovery <antoniocabreraperez gmail.com> writes:
On Monday, 14 December 2020 at 12:22:26 UTC, ddcovery wrote:
     int opCmp(Number other){
       return _value - other.value;
     };
Correction: bool opEquals(Number other){ return _value == other.value; };
Dec 14 2020
parent reply Q. Schroll <qs.il.paperinik gmail.com> writes:
On Monday, 14 December 2020 at 14:39:14 UTC, ddcovery wrote:
 On Monday, 14 December 2020 at 12:22:26 UTC, ddcovery wrote:
     int opCmp(Number other){
       return _value - other.value;
     };
Correction: bool opEquals(Number other){ return _value == other.value; };
You could just give the struct a variable and use that instead of the enclosing function's parameter: https://run.dlang.io/is/4Lqf15 Then, the struct can actually be static.
Dec 15 2020
parent ddcovery <antoniocabreraperez gmail.com> writes:
On Tuesday, 15 December 2020 at 19:53:33 UTC, Q. Schroll wrote:
 On Monday, 14 December 2020 at 14:39:14 UTC, ddcovery wrote:
 On Monday, 14 December 2020 at 12:22:26 UTC, ddcovery wrote:
     int opCmp(Number other){
       return _value - other.value;
     };
Correction: bool opEquals(Number other){ return _value == other.value; };
You could just give the struct a variable and use that instead of the enclosing function's parameter: https://run.dlang.io/is/4Lqf15 Then, the struct can actually be static.
First of all, thanks for maintaining opCmp... reading documentation I thought that == and != needed a opEquals method... but opCmp is enough. Your solution is really nice for the example, but at the cost of eliminating the closure ( In fact, the function is not necessary either: the structure itself is sufficient for the example). As I understand, problem is that calling "number" function from struct is not possible because "number" should return an struct definition that doesn't exist (because it's definition is not finished yet). It is similar to the problem with recursive lambda call using an "proxy" variable: const factorial = (int n) => n==0 ? 1 : n * factorial(n-1); *factorial* is not defined yet when compiler analyzes lambda expression. This is something to keep in mind for people coming from python/javascript languajes. Sometimes I forget D is not an scripting/dynamic one (note: crystal has the same limitation... it says "Error: can't use variable name 'factorial' inside assignment to variable 'factorial'").
Dec 15 2020