Languages such as C/C++ and Java follow an “eager” argument evaluation approach, where function arguments are evaluated before the function is entered. Of course, there are idioms and tricks that one can use to force “lazy” evaluation. The primary benefit of “lazy” parameter evaluation is that the parameter is evaluated only when it is used and this can improve efficiency. D language supports both “eager” and “lazy” parameter evaluations.
Here is a simple D program to show “eager” parameter evaluation:
If you study the function “fooBar”, it takes a boolean first parameter along with two integer params. Based on the value of the first param, it uses one of the other two params (not both) inside the body for computing its result.
Now look at the program output:
We see that both the functions are evaluated in each case. This is not surprising. Because by default, D language (like C, C++, Java) uses “eager evaluation“, when the “fooBar” function is called, both the second and third parameters are evaluated apriori, even though only one is actually used inside the function. One might argue that it is “wasteful” to call the other function that is not used in the result computation, especially if the calculation is “costly”.
The solution lies in “lazy” parameter evaluation. Here is the modified “fooBar” function:
I have added the extra qualifier “lazy” to the second and third parameters of “fooBar”. This forces the D compiler to evaluate the argument(s) only at the point of use, not apriori. This is confirmed by the output from the program.
Nice, isn’t it? There is a catch, though. While the positive aspect of declaring an argument as “lazy” is that the compiler evaluates it only when it is required, the negative side of it is that the compiler evaluates it “every” time it needs the parameter.
Let us modify our “fooBar” function slightly:
The change, as you would have noticed, is that I am using the “lazy” parameters twice in each expression just to prove a point. When we run the program now, this is what we get:
Clearly, this is not what we want! Our decision to declare the parameters as “lazy” in the first place was to avoid unnecessary computation, but now the objective is lost!
So what is the way out? Simple really. We can evaluate the “lazy” parameter once and assign it to a different local variable and then use that local variable whenever we need the original parameter later in the function. This is shown below.
And here is the program output after the change:
That solves our problem! We now have the benefit of “lazy” parameter evaluation, at the same time avoiding multiple evaluations of that parameter. Ideally, the compiler should cache the result of the first evaluation and use it subsequently, but we can live with that limitation.
You can download the sample D program here.
Have a nice weekend!
Recent Comments