Thread overview
closures + struct: Error: forward reference to inferred return type of function call
Dec 14
ddcovery
Dec 14
ddcovery
Dec 15
ddcovery
December 14
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.


December 14
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;
};
December 15
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.
December 15
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'").