A nested function is a function defined inside the scope of a function. Like other nested objects, a nested function is not visible outside of its enclosing function but can access members and objects of its enclosing function and anything that encloses it. Let's take a look at how they work in D.
import std.stdio;int enclosingFun(int a){int nestedFun(int b){int nestedFun2() { return 1; }return b + nestedFun2();}return nestedFun(a);}void main(){int i = enclosingFun(3); // i is assigned 4writeln(i);}
In the above example, we have a function called enclosingFun()
that nests a function named nestedFun()
which in turn nests another function known as nestedFun2()
. The nestedFun()
takes the argument provided by enclosingFun()
and passes them on to nestedFun2()
. Like in all nested procedures, the most nested function executes first, which in our case is nestedFun2()
.
Let's now explore some constraints of nested functions through the example below.
import std.stdio;int enclosingFun(int a){int nestedFun(int b) { return b + 1; } // okreturn nestedFun(a);}void main(){int i = enclosingFun(3); // okwriteln(i);int j = enclosingFun(3).nestedFun(3); // error, enclosingFun.nestedFun2 not visible}
In the above example, we have a function with a nested function within it. In main()
, we have an error on line 13. The reason is that nestedFun()
only exists in the scope of enclosingFun()
. If we try to call it from the main()
function, it causes an error. We can comment out line 13 to remove the error.
A nested function can access any data or objects present in its enclosing function and any function that may enclose that function. Let's visualize this concept with a code example.
import std.stdio;int encloseFun(int a){int c = 3;int nestLevel1(int b){int nestLevel2(){return c; // access encloseFun.c}return b + c + nestLevel2(); // 3 + 3 + 3}return nestLevel1(3);}void main(){int i = encloseFun(3);writeln(i);}
In the above function, we have a function called enclosedFun()
, which nests a function called nestLevel1()
. This function, in turn, nests another function called nestLevel2()
. In line 11, we access the variable c
,which is defined on line 5 in the scope of enclosedFun()
. This example follows the rules of nesting and is allowed.
Let's examine what happens when we make nested functions that are also static. In a case like this, the static nested function cannot access any stack variables of its enclosing functions. Still, it can access any variables with the static modifier. Please refer to the example below.
import std.stdio;int enclosingFun(int a){int c;static int d;static int nestedFun(int b){b = d; // assigning the value of d to b is allowedb = c; // error, nestedFun() cannot access frame of enclosingFun()return b + 1;}return nestedFun(a);}void main(){int i = enclosingFun(3);writeln(i);}
As we can see in the above example, the static nestedFun()
tries to access the stack variable c
on line 11, resulting in an error. However, when trying to access the static variable, d
there is no error. We can comment out line 11 to get rid of the error.
Nesting functions are also possible inside member functions of a class or a structure. See the code snippets below for examples.
import std.stdio;struct ExStruct{int a = 5;int enclosedFun(){int c = 5;int nestedFun(){return c + a;}return nestedFun();}}void main(){auto s = new ExStruct();writeln(s.enclosedFun());}
In the above code snippet, we define a structure that contains a variable, a member function called enclosedFun()
, which nests a function called nestedFun()
. The nestedFun()
returns the sum of the variables c
(defined in the enclosedFun()
and a
(defined in the structure). In main()
, we create an object of the structure and call the member function.
import std.stdio;class ExClass{int a = 5;int enclosedFun(){int c = 5;int nestedFun(){return c + a;}return nestedFun();}}void main(){auto s = new ExClass();writeln(s.enclosedFun());}
In the above example, we do the same as we did in the code snippet with the structure, the only difference is that we have replaced the structure with a class.