The following would cause stack overflow for large ‘n’, and I can understand why.
def factorial(n)
(n > 1) ? (return (n * factorial(n - 1))) : (return 1)
end
Why does the following cause overflow as well?
def factorial(n, k)
(n > 1) ? (return factorial(n - 1, lambda {|v| return k.call(v * n)})) : (return k.call(1))
end
Your second algorithm creates a
n-long chain of lambda procedures, each containing a reference to the previous one. I don’t know exactly what Ruby does, but in a properly tail-recursive language the stack would not overflow in your second algorithm, becausek.callin the lambda is also in tail position. If, as Brian’s experiment suggests, Ruby doesn’t have proper tail calls, then-long chain of nested calls to the lambda will overflow the stack when the head of the chain is invoked, even though Ruby is smart enough to convert the tail-recursivefactorialcall into a loop (= tail-call optimisation).