Yes, and fold() is not returning a value in the case where begin != end. |
Right you are, sir. I only noticed that.
The first call to
fold never returns; yet to my surprise it still works:
sun@dhcppc1:~/devf/c++$ head -14 fold.c++
#include <iostream>
#include <functional>
/*
Taking a sequence and producing a single
value from it one-by-one is called `folding'.
*/
template <typename T, typename C>
T fold (C closure, T seed, T *begin, T *end)
{
if (begin != end) fold (closure, closure(seed, *begin), begin+1, end);
else return seed;
}
sun@dhcppc1:~/devf/c++$ c++ fold.c++ && ./a.out
Summation of 1,2,3,4,5 = 15
Randomness, factorial of 5 is 120
|
Since the first call never returns any value, it should not return a value at all.
I think the only logical explanation is that the compiler eliminates the tail recursion.
That is understandable, since even LISP standard mandates that all tail recursions be recognized and optimized.
I'm sure this behavior is documented somewhere in the C++ standard also and is not peculiar to my compiler.
OR:
The problem is more low level. I think this must be it.
The last call to
fold sets the accumulator to the value of
seed.
Since we are not performing further calculations in fold() before returning the value (such as addition or subtraction)
the value of the accumulator register remains unchanged when fold() unfolds and stack is rewinded.
Let me verify the 2nd option. I'll post again in a sec (or edit this post)
[EDIT]
Hmm, I was correct as to why the correct answer was being returned. It was all because
int was the return value.
The following experiment had positive results.
sun@dhcppc1:~/devf/c++$ head -18 fold.c++ | tail
[code]
T fold (C closure, T seed, T *begin, T *end)
{
volatile int r = 0, x = 2;
if (begin != end) {
fold (closure, closure(seed, *begin), begin+1, end);
r += x; // perform some calculation, r = 2 now.
}
else
return seed;
}
[/code]
sun@dhcppc1:~/devf/c++$ c++ fold.c++ && ./a.out
Summation of 1,2,3,4,5 = 2
Randomness, factorial of 5 is 2
|
Now the return value is 2 -- the value computed in r, which is clearly not what I'm returning.
So, the reason wasn't because my compiler was eliminating tail recursion... it's because the
fold function is too simple and the first call to
fold wasn't returning anything.
Well, Mr. Smith was right.