www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Forward referencing functions in D

reply wilcro <wmcr mail.com> writes:
The web page "Programming in D for C Programmers" 
(https://dlang.org/articles/ctod.html#forwardfunc) states that 
forward declarations are neither required nor permitted, and that 
the following construct is allowable:

void myfunc()
{
     forwardfunc();
}

void forwardfunc()
{
     ... //do stuff
}


However, the following code will cause a compiler error:

import std.stdio: writeln;

void main()
{

     void myfunc() {

         forwardfunc(); // onlineapp.d(8): Error: undefined 
identifier forwardfunc
     }

     void forwardfunc() {

         writeln("foo");
     }

     myfunc();

}


Evidently, I am misunderstanding something very elemental here; 
thanks for any enlightenment regarding this.
Oct 16 2020
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 16 October 2020 at 19:55:53 UTC, wilcro wrote:
 Evidently, I am misunderstanding something very elemental here; 
 thanks for any enlightenment regarding this.
Inside a function things happen in order, top to bottom, including declarations (you can only access local variables after they are declared, and nested functions work like local variables). In a declaration, order is less important. For recursive nested functions it can sometimes help to put a declaration inside a function: void main() { // order matters here, in function struct Holder { // order doesn't matter in here, in decl } // order matters again since functions run in sequence }
Oct 16 2020
prev sibling next sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Friday, 16 October 2020 at 19:55:53 UTC, wilcro wrote:
 The web page "Programming in D for C Programmers" 
 (https://dlang.org/articles/ctod.html#forwardfunc) states that 
 forward declarations are neither required nor permitted, and 
 that the following construct is allowable:

 void myfunc()
 {
     forwardfunc();
 }

 void forwardfunc()
 {
     ... //do stuff
 }


 However, the following code will cause a compiler error:

 import std.stdio: writeln;

 void main()
 {

     void myfunc() {

         forwardfunc(); // onlineapp.d(8): Error: undefined 
 identifier forwardfunc
     }

     void forwardfunc() {

         writeln("foo");
     }

     myfunc();

 }


 Evidently, I am misunderstanding something very elemental here; 
 thanks for any enlightenment regarding this.
I think it might be just because you havent defined the function yet at that point.
Oct 16 2020
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Oct 16, 2020 at 08:04:07PM +0000, Imperatorn via Digitalmars-d-learn
wrote:
[...]
 I think it might be just because you havent defined the function yet
 at that point.
That's not correct; the following works: module mymodule; void func() { forwardfunc(); } void forwardfunc() { } However, this only applies in module scope. If they were declared inside a function body, forwardfunc must be declared before func. T -- It is impossible to make anything foolproof because fools are so ingenious. -- Sammy
Oct 16 2020
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Oct 16, 2020 at 07:55:53PM +0000, wilcro via Digitalmars-d-learn wrote:
 The web page "Programming in D for C Programmers"
 (https://dlang.org/articles/ctod.html#forwardfunc) states that forward
 declarations are neither required nor permitted,
[...]
 However, the following code will cause a compiler error:
[...]
 void main()
 {
 
     void myfunc() {
 
         forwardfunc(); // onlineapp.d(8): Error: undefined identifier
 forwardfunc
     }
 
     void forwardfunc() {
 
         writeln("foo");
     }
[...] This is because order-independence of declarations only applies to module scope, not to function scope. So the above would work if myfunc and forwardfunc were moved outside of main(). But inside a function body, you must declare everything before you use them. T -- Philosophy: how to make a career out of daydreaming.
Oct 16 2020
prev sibling next sibling parent reply wilcro <wmcr mail.com> writes:
On Friday, 16 October 2020 at 19:55:53 UTC, wilcro wrote:
 The web page "Programming in D for C Programmers" 
 (https://dlang.org/articles/ctod.html#forwardfunc) states that 
 forward declarations are neither required nor permitted, and 
 that the following construct is allowable:

 void myfunc()
 {
     forwardfunc();
 }

 void forwardfunc()
 {
     ... //do stuff
 }


 However, the following code will cause a compiler error:

 import std.stdio: writeln;

 void main()
 {

     void myfunc() {

         forwardfunc(); // onlineapp.d(8): Error: undefined 
 identifier forwardfunc
     }

     void forwardfunc() {

         writeln("foo");
     }

     myfunc();

 }


 Evidently, I am misunderstanding something very elemental here; 
 thanks for any enlightenment regarding this.
Thanks to all for your responses; as a related followup question, would there be any reason to avoid placing the majority of code for a program outside of the main function?
Oct 16 2020
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/16/20 1:47 PM, wilcro wrote:

 would
 there be any reason to avoid placing the majority of code for a program
 outside of the main function?
Keeping scopes of symbols as small as possible is a general guideline in D and elsewhere but I wouldn't crowd my main() function with details of program logic either. (Aside: There is no global name scope in D; everything belongs to a module.) One thing I love about D is that there are no strong principles like that. I code in a way that is comfortable and change things later on as a needs arise. :) Ali
Oct 16 2020
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/16/20 4:47 PM, wilcro wrote:

 
 Thanks to all for your responses; as a related followup question, would 
 there be any reason to avoid placing the majority of code for a program 
 outside of the main function?
Inner functions have benefits: 1. They are only accessible inside the function. Which means you only have to worry about correctness while INSIDE that function. 2. inner functions have access to the outer function's stack frame. Often, I use inner functions to factor out a common piece of code that I don't want to have to write multiple times in the same function. -Steve
Oct 16 2020
parent reply NonNull <non-null use.startmail.com> writes:
On Friday, 16 October 2020 at 21:28:18 UTC, Steven Schveighoffer 
wrote:
 Inner functions have benefits:

 1. They are only accessible inside the function. Which means 
 you only have to worry about correctness while INSIDE that 
 function.
 2. inner functions have access to the outer function's stack 
 frame.

 Often, I use inner functions to factor out a common piece of 
 code that I don't want to have to write multiple times in the 
 same function.

 -Steve
How can you write two inner functions that call each other? (Recursively)
Oct 17 2020
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/17/20 8:28 AM, NonNull wrote:
 On Friday, 16 October 2020 at 21:28:18 UTC, Steven Schveighoffer wrote:
 Inner functions have benefits:

 1. They are only accessible inside the function. Which means you only 
 have to worry about correctness while INSIDE that function.
 2. inner functions have access to the outer function's stack frame.

 Often, I use inner functions to factor out a common piece of code that 
 I don't want to have to write multiple times in the same function.

 -Steve
How can you write two inner functions that call each other? (Recursively)
I thought of the following method just now. Yes, there are lambdas but who cares? :) (Besides, 'a' can be defined as a proper function below.) import std.range; void foo(string s) { // b is not initialized yet void delegate() b; // a is initialized auto a = { while (!s.empty) { s.popFront(); b(); } }; // Set b to a lambda b = { while (!s.empty) { s.popBack(); a(); } }; a(); } void main() { foo("hello"); } Ali
Oct 17 2020
prev sibling parent wilcro <wmcr mail.com> writes:
On Friday, 16 October 2020 at 19:55:53 UTC, wilcro wrote:
 The web page "Programming in D for C Programmers" 
 (https://dlang.org/articles/ctod.html#forwardfunc) states that 
 forward declarations are neither required nor permitted, and 
 that the following construct is allowable:

 void myfunc()
 {
     forwardfunc();
 }

 void forwardfunc()
 {
     ... //do stuff
 }


 However, the following code will cause a compiler error:

 import std.stdio: writeln;

 void main()
 {

     void myfunc() {

         forwardfunc(); // onlineapp.d(8): Error: undefined 
 identifier forwardfunc
     }

     void forwardfunc() {

         writeln("foo");
     }

     myfunc();

 }


 Evidently, I am misunderstanding something very elemental here; 
 thanks for any enlightenment regarding this.
Thanks for your insights, Ali and Steve -- very helpful.
Oct 16 2020