www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Calling nested function before declaration

reply Jonathan <JonathanILevi gmail.com> writes:
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?
Sep 26 2018
next sibling parent reply Neia Neutuladh <neia ikeran.org> writes:
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.
Sep 26 2018
parent Timon Gehr <timon.gehr gmx.ch> writes:
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 }
Sep 27 2018
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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.
Sep 27 2018
parent Walter Bright <newshound2 digitalmars.com> writes:
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.
Sep 27 2018
prev sibling parent nkm1 <t4nk074 openmailbox.org> writes:
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; }
Sep 27 2018