Your Pascal's triangle algorithm is incorrect, but maybe you haven't finished it yet, so I'm not going to tell you how to write a correct algorithm, just how to stop the stack overflow.
EDIT: maksimov is right that by forgetting to wrap your else
sequence in braces, you are only making the first expression conditional, which means that the second expression is always evaluated and loops infinitely into stack overflow. Adding the braces, however, will only change a 100% probability of stack overflow into a possibility of a stack overflow, because the calls to your pascal
function are not in tail position. To remove the risk of stack overflow, you have to make further modifications, explained below...
Recursive functions can avoid stack overflows by using tail recursion. However, for that to work, the recursive call has to be in tail position. That is, the recursive call must be the final expression to be executed before the function returns and its value must be returned without modification, all the way back up the stack to the first invocation. Since your calculation uses pascal(r, c-1) * (r-c)/c
, you are always modifying the returned value before returning that modified result, so the call is not in tail position. You need to modify your function so that when it finally returns it gives the correct result with no need for modification. The end result should have this basic shape...
def pascal(c: Int, r: Int): Int = {
...
if (c <= 0) 1 else pascal(..., ...)
}
You will find that the only way to do this is to define a local function inside your pascal function and have that do the recursion....
def pascal(c: Int, r: Int): Int = {
def loop(...): Int = ... match {
case ... => 1
case ... => x + y
case ... => loop(...)
case _ => loop(...)
}
...
if (c <= 0) 1 else loop(...)
}
This is because the recursive function will have to check state to find out whether it has solved the final problem or a sub-task within the problem. The state can be extra parameters passed to loop
or local vars defined at the top level of pascal
Only once you have safely moved the recursion into the local function can you safely do what maksimov suggested
var p = if (c <= 0) 1 loop(...)
println(p)
p
You can do this safely because the recursive calls all happen inside loop
and are all (if you use my template) in tail position.
To be clear: having two successive calls to your pascal
function is not the cause of the overflow. The two top-level calls in your code are sequential and do not interfere with each other; if one completes, so will the other. If the first fails, the second one would also have failed (and removing the first one will not stop the second one from failing).