Thread overview
Calling nested function before declaration
Sep 26, 2018
Jonathan
Sep 26, 2018
Neia Neutuladh
Sep 27, 2018
Timon Gehr
Sep 27, 2018
Timon Gehr
Sep 27, 2018
Walter Bright
Sep 28, 2018
nkm1
September 26, 2018
This code fails to compile: ("undefined identifier fun")
void main() {
    fun();
    void fun() {}
}

Having the call after the declaration works:
void main() {
    void fun() {}
    fun();
}

Is this how it is intended to work?

It seems goofy that this works:
void main() {
    void fun2() {}
    void fun() {
         fun2()
    }
    fun();
}

But this fails to compile: ("undefined identifier fun2")
void main() {
    void fun() {
         fun2()
    }
    void fun2() {}
    fun();
}

What if I wanted this?
void main() {
    void fun2() {fun();}
    void fun() {fun2();}
    fun();
}

I can't see how the current behavior is at all better or to be preferred unless it is faster to compile?  What is the reason for it being how it is?
September 26, 2018
On 09/26/2018 03:46 PM, Jonathan wrote:
> I can't see how the current behavior is at all better or to be preferred unless it is faster to compile?  What is the reason for it being how it is?

void outerFunction()
{
  func();
  auto lock = acquireLock();
  void nested()
  {
  }
}

Inside `nested`, can you refer to `lock`? It's in lexical scope, so yes. It hasn't been initialized yet. What value should it have? Presumably its standard uninitialized value.

This is likely to cause a lot of confusion.

The standard ways of dealing with this:

* Reorder the declarations.
* Make the functions non-nested.
* Get rid of mutual recursion.
* Use a delegate.
* Do a method-to-method-object refactoring.
September 27, 2018
On 27.09.2018 01:05, Neia Neutuladh wrote:
> 
> The standard ways of dealing with this:
> 
> * Reorder the declarations.
> * Make the functions non-nested.
> * Get rid of mutual recursion.
> * Use a delegate.
> * Do a method-to-method-object refactoring.

* turn the function with the forward reference into a template

void main() {
    void fun()() {
        fun2();
    }
    void fun2() {}
    fun(); // ok
}
September 27, 2018
On 27.09.2018 00:46, Jonathan wrote:
> 
> 
> I can't see how the current behavior is at all better or to be preferred unless it is faster to compile?  What is the reason for it being how it is?

The current behavior is easy to specify and simple to implement, and it is what Walter has implemented. A better behavior that is almost as simple to implement would be to insert nested functions into the symbol table in blocks of back-to-back-defined nested functions, but that would be a breaking language change at this point. (Maybe you can get a DIP though though.) Otherwise, the template workaround is a bit ugly but it works and is non-intrusive.
September 27, 2018
On 9/27/2018 11:33 AM, Timon Gehr wrote:
> The current behavior is easy to specify and simple to implement, and it is what Walter has implemented. A better behavior that is almost as simple to implement would be to insert nested functions into the symbol table in blocks of back-to-back-defined nested functions, but that would be a breaking language change at this point. (Maybe you can get a DIP though though.) Otherwise, the template workaround is a bit ugly but it works and is non-intrusive.

Right. Functions tend to be short, and it's very rare that a function cannot be defined before use. One such case is mutually recursive functions. But as Timon showed, there is a simple workaround for this, and has been suggested, a delegate can be used, too.

And as Timon also suggested, the straightforwardness of the existing approach is an advantage and is intended.
September 28, 2018
On Wednesday, 26 September 2018 at 22:46:21 UTC, Jonathan wrote:
> This code fails to compile: ("undefined identifier fun")
> void main() {
>     fun();
>     void fun() {}
> }
>
> Having the call after the declaration works:
> void main() {
>     void fun() {}
>     fun();
> }
>
> Is this how it is intended to work?
>
> It seems goofy that this works:
> void main() {
>     void fun2() {}
>     void fun() {
>          fun2()
>     }
>     fun();
> }
>
> But this fails to compile: ("undefined identifier fun2")
> void main() {
>     void fun() {
>          fun2()
>     }
>     void fun2() {}
>     fun();
> }
>
> What if I wanted this?
> void main() {
>     void fun2() {fun();}
>     void fun() {fun2();}
>     fun();
> }
>
> I can't see how the current behavior is at all better or to be preferred unless it is faster to compile?  What is the reason for it being how it is?

One of the reasons is consistency perhaps. Functions are not different from other identifiers:

void fun1()
{
    writeln(x);
}

int x = 1;

void fun2()
{
    writeln(y); // fails ("undefined indentifier y")
    int y = 2;
}