I am having problems running the below recursive function on our development web server. It causes a stack overflow. It runs fine locally when in debugging mode. Here are things I have tried:
- Made sure ‘Generate tail calls’ is enabled under build options.
- I ran the disassembler and followed the instructions here: http://blogs.msdn.com/b/fsharpteam/archive/2011/07/08/tail-calls-in-fsharp.aspx and it does not appear to be using tail recursion.
- I’ve tried rewriting it without using recursion but my F# skills are not the best.
So my questions would be:
- Is this function going to be able to use tail end recursions?
- Why would it work locally in debugging mode through VS but not on the dev web server?
Thanks!
let rec SimulationLoop (rowNum : int) (h : double) (time : double) (v : double) (s : double) (p : double) (newV' : double) (newS' : double) (newP' : double) (designParameters : DesignParameters) (inputs : ISimulationInputProvider) = seq {
//let timer = System.Diagnostics.Stopwatch.StartNew()
let finalTime = (6.0 * inputs.ShockAbsorber.Stroke / designParameters.VelocityAfterImpact)
let startH = StartH h time finalTime
let slopes = Slopes v s p newV' newS' newP' startH designParameters inputs
let vSlope, sSlope, pSlope = slopes
let betaList = [ for j in 0 .. 5 -> beta.[j].[4] ]
let newV' = CalcPrime v startH vSlope betaList
let newS' = CalcPrime s startH sSlope betaList
let newP' = CalcPrime p startH pSlope betaList
let delta = Delta h slopes
let tau = Tau v s p
let rowResult, rowNum, time, newV, newS, newP = if delta < tau then RecordResults rowNum time startH v s p slopes designParameters inputs else None, (rowNum + 1), time, v, s, p
let loop = newS < inputs.ShockAbsorber.Stroke - 0.01 && newV >= 0.0 && rowNum <= 8000 && (time < finalTime && time + h > time)
let stepLength = StrokeStepLength inputs.ShockAbsorber.Stroke designParameters.HoleSize
let endH = EndH delta startH tau stepLength newV
//timer.Stop()
//System.Diagnostics.Debug.WriteLine("Row: " + rowNum.ToString() + " = " + timer.ElapsedMilliseconds.ToString())
match (rowResult, loop) with
| Row(r), true ->
yield r
yield! SimulationLoop rowNum endH time newV newS newP newV' newS' newP' designParameters inputs
| Row(r), false ->
yield r
| None, true ->
yield! SimulationLoop rowNum endH time newV newS newP newV' newS' newP' designParameters inputs
| None, false -> ()
}
I ended up rewriting it without recursion. This is not the most elegant solution but it works: