Answer : No Option is correct.
Answer to this question can be found in the Example 6 below.
"Call by name" parameter passing technique was used by some imperative languages like Algol W, and it is used by several functional languages, like Haskell.
We'll see how "Call by name" parameter passing technique works(theoretical Idea for understanding its working), Not how it is actually implemented(practical implementation).
How "Call by name" works (Idea of this technique) :
In general, the effect of pass-by-name is to textually substitute the argument expressions(actual parameters) in a procedure call for the corresponding parameters(formal parameters) in the body of the called procedure.*
i.e. Direct Substitution of actual parameters in the place of formal parameter in the called procedure.*
(* means that it is not complete definition/statement and some technical details are missing and as we go on, we'll fill in these details.)
Example 1 : What will be the output if "Call by name" parameter passing technique is used.
Given Program :
void P(x) {
print(x+10);
print (x);
}
main()
{
int j = 10;
P(j);
}
Answer : Since "Call by name" parameter passing technique is used, we can re-write the program as following :
void P(x) {
print(j+10);
print (j);
}
main()
{
int j = 10;
P(j);
}
Hence, output : 20,10
NOTE 1 (Technical Detail 1) : It does Not matter which Scoping is used(static or dynamic), Once we substitute Actual arguments in the place of formal parameters in the called function, for those variables in the actual arguments, Environment of caller function will be applicable.
Hence, in the above example 1, in function P, $j$ refers to the $j$ of the caller function i.e. main function.
Example 2 will illustrate the Note 1.
Example 2 : What will be the output if "Call by name" parameter passing technique is used in case of static and dynamic scopings?
global int j=100;
void P(x) {
print(x+10);
print (x);
}
main()
{
int j = 10;
P(j);
}
Answer : Since "Call by name" parameter passing technique is used, we can re-write the program as following :
global int j=100;
void P(x) {
print(j+10);
print (j);
}
main()
{
int j = 10;
P(j);
}
In case of Dynamic scoping : 20,10
In case of Static scoping : 20,10
Note that in case of Static scoping, $j$ in function P does not refer to the global variable But $j$ refers to the caller function, more precisely, Once we substitute Actual arguments in the place of formal parameters in the called function, for those variables in the actual arguments, Environment of caller function will be applicable. Hence, $j$ in P will be accessed/updated accroding to caller function's environment and since, caller function i.e. main function here, has a local variable $j$, so, this $j$ will be accessed/updated by function P.
Example 3 : What will be the output if "Call by name" parameter passing technique is used in case of static and dynamic scopings?
global int j=100;
void P(x) {
print(x+10);
print (x);
}
main()
{
P(j);
}
Answer : Since "Call by name" parameter passing technique is used, we can re-write the program as following :
global int j=100;
void P(x) {
print(j+10);
print (j);
}
main()
{
P(j);
}
In case of Dynamic scoping : 110,100
In case of Static scoping : 110,100
Again, Once we substitute Actual arguments in the place of formal parameters in the called function, for those variables in the actual arguments, Environment of caller function will be applicable. Hence, $j$ in P will be accessed/updated accroding to caller function's environment and since, caller function i.e. main function here, does not have a local variable $j$, environment of function main for variable $j$ would depend on the scoping used, But this scoping will be seen from the perspective of caller function i.e. function main, Not from the perspective of called function i.e. function P. So, it is like accessing variable $j$ in the main function, not in P function. Hence, for this example 3, in both scoping, the main function will be using Global variable $j.$
Example 4 : What will be the output if "Call by name" parameter passing technique is used in case of static and dynamic scopings?
global int j=100, i = 300;
void Q(x) {
print(x+10);
print (x); }
void P(x) {
print(x+10);
Q(i);
print (x);
}
main()
{
int i =500;
int j =10;
P(j);
}
Answer : Since "Call by name" parameter passing technique is used, we can re-write the program as following :
global int j=100, i = 300;
void Q(x) {
print(i+10); // this i refers to i in the caller function i.e. P function's environment
print (i); } // this i refers to i in the caller function i.e. P function's environment
void P(x) {
print(j+10); // this j refers to j in the caller function i.e. main function's environment
Q(i);
print (j); // this j refers to j in the caller function i.e. main function's environment
}
main()
{
int i =500;
int j =10;
P(j);
}
In case of Dynamic scoping : 20,510,500,10
In case of Static scoping : 20,310,300,10
In Static scoping, variable $i$ in P function's environment refers to the global variable $i$. In Dynamic scoping, variable $i$ in P function's environment refers to the main function's $i.$
NOTE 2 (Technical Detail 2) :
if any of the local variables in the called procedure clash with the caller's variables, they(called function's clashing variables) must be renamed uniquely before substitution.
Example 5 : What will be the output if "Call by name" parameter passing technique is used.
Given Program :
void P(x) {
int j=100;
print(x+10);
print(j);
print (x);
}
main()
{
int j = 10;
P(j);
}
Answer : Since "Call by name" parameter passing technique is used, we can re-write the program as following :
Caller function's Actual argument conatins variable $j$ which clashes with called function P's local variable $j,$ hence, we rename called function P's local variable $j$ and change it to $j'.$
void P(x) {
int j'=100;
print(j+10); // this j refers to j in the caller function i.e. main function's environment
print(j'); // this j' refers to the local variable j' in P.
print (j); // this j refers to j in the caller function i.e. main function's environment
}
main()
{
int j = 10;
P(j);
}
Hence, output : 20,100, 10.
Coming to the actual GATE question, we'll call it example 6.
Example 6 : What will be the output if "Call by name" parameter passing technique is used, in case of static and dynamic scopings?
global int i=100, j=5;
void P(x) {
int i=10;
print(x+10);
i=200;
j=20;
print (x);
}
main() {P(i+j);}
Answer : Since "Call by name" parameter passing technique is used, we can re-write the program as following :
Caller function's Actual argument conatins variable $i$ which clashes with called function P's local variable $i,$ hence, we rename called function P's local variable $i$ and change it to $i'.$
global int i=100, j=5;
void P(x) {
int i'=10; // this i' refers to the local variable i' in function P.
print(i+j+10); // this i,j refers to i,j in the caller function i.e. main function's environment
i'=200; // this i' refers to the local variable i' in function P.
j=20; // this j refers to j in the caller function i.e. main function's environment
print (i+j); // this i,j refers to i,j in the caller function i.e. main function's environment
}
main() {P(i+j);}
In case of Static scoping : 115, 120
In case of Dynamic scoping : 115, 120
Note that there are no local variable $i,j$ in main function, so, when we say that $i,j$ refer to the $i,j$ in main's environment , we mean that If $i,j$ were accessed/updated in main function then depending on the scoping, which $i,j$ would they refer.
Here, in this question, in both static and dynamic scoping case, $i,j$ will refer to the Global variables.
And in function P, in the 4th statement (i.e. $j = 20$), the Gloabl variable $j$ will be updated.
Hence, No Option is correct for the actual above GATE question.
Example 7: What will be the output if "Call by name" parameter passing technique is used in case of static and dynamic scopings?
global int j=100, i = 300;
void Q(x) {
print(x+10);
print (x); }
void P(x) {
int i = 400;
int j = 600;
print(x+10);
Q(i);
Q(j);
print (x);
}
main()
{
int i =500;
Q(i);
int j =10;
P(j);
}
Answer :
in both scoping, for this question, output : 510,500,20,410,400,610,600,10.
Note that When main calls $P(j)$, then Caller function main's Actual argument conatins variable $j$ which clashes with called function P's local variable $j,$ hence, we rename called function P's local variable $j$ and change it to $j'.$ So, in function P, the 5th statement becomes $Q(j').$
Also note that when main calls Q(i), then $x$ in Q is replaced with $i.$ When P calls Q(i), then $x$ in Q is replaced with $i.$ When P calls Q(j'), then $x$ in Q is replaced with $j'.$
Note that "Direct Substitution of actual parameters in the place of formal parameter in the called procedure" is only the Idea of Call-by-name, Not the actual practical implementation. Compiler does Not do Direct Substitution blindly. Pass-by-name is difficult to implement. Argument expressions must be compiled to special parameterless procedures called thunks. These thunks are passed into the called procedure and used whenever necessary to evaluate or re-evaluate the argument.
But we do not need to go into practical implementation details because the Idea remains same. Hence, we can solve all the questions using above idea of call-by-name.
NOTE 3 (Technical Detail 3) :
if any of the variables in the called procedure clash with the caller's variables, they(called function's clashing variables) must be renamed uniquely before substitution.
Clashing variables need not be local variables of the called function.
But remeber that when we rename a variable, we don't really rename it. We rename it just to eliminate the possibility of confusion. So, when we rename $j $ to $j'$, we must not foget that $j'$ is actually $j$ only in the first place.
The following example will illustrate this point :
Example 8: What will be the output if "Call by name" parameter passing technique is used in case of static and dynamic scopings?
global int j=100, i = 300;
void Q(x) {
print(i);
print(j);
print(x+10);
print (x); }
void P(x) {
int i = 400;
int j = 600;
print(x+10);
Q(i);
Q(j);
print (x);
}
main()
{
int i =500;
int j =10;
Q(i);
P(j);
}
Answer :
In case of Static scoping : 300, 100, 510, 500, 20, 300, 100, 410, 400, 300, 100, 610, 600, 10
In case of Dynamic scoping : 500, 10, 510, 500, 20, 400, 600, 410, 400, 400, 600, 610, 600, 10
global int j=100, i = 300;
void Q(x) {
print(i); // this i refers to the Global i in case of static scoping and in case of dynamic scoping, according to the calling function in the stack.
print(j); // this j refers to the Global j in case of static scoping and in case of dynamic scoping, according to the calling function in the stack.
print(x+10); // variables that are substituted here, refer to the corresponding variables in the caller function's environment
print (x); } // variables that are substituted here, refer to the corresponding variables in the caller function's environment
void P(x) {
int i = 400;
int j = 600;
print(x+10); // variables that are substituted here, refer to the corresponding variables in the caller function's environment
Q(i);
Q(j);
print (x); // variables that are substituted here, refer to the corresponding variables in the caller function's environment
}
main()
{
int i =500;
int j =10;
Q(i);
P(j);
}
When main calls $Q(i) ,$ we substitute $i$ in place of $x$ and it(Q) becomes :
void Q(x) {
print($i'$); // This is renamed as $i'$ and it refers to global variable $i$ in case of static scoping and in case of dynamic scoping it refers to variable $i$ in main function.
print($j$);
print($i+10$);
print ($i$); }
Hence, the two different $i's$ should be distinguished properly.
https://www2.cs.sfu.ca/~cameron/Teaching/383/PassByName.html
https://www2.cs.arizona.edu/classes/cs520/spring06/06parameters.pdf