我在開發Web服務器上運行下面的遞歸函數時遇到問題。它會導致堆棧溢出。在調試模式下,本地運行良好。這裏是我已經嘗試過的東西:當不在本地運行時,F#尾遞歸堆棧溢出
- 確保在生成選項下啓用了「生成尾呼叫」。
- 我跑了反彙編程序,並按照這裏的說明:http://blogs.msdn.com/b/fsharpteam/archive/2011/07/08/tail-calls-in-fsharp.aspx它不會出現要使用尾遞歸。
- 我試過重寫它而不使用遞歸,但我的F#技能不是最好的。
所以我的問題是:
- 是這個功能將能夠使用尾部遞歸?
- 爲什麼它會在調試模式下通過VS本地工作,而不是在開發Web服務器上?
謝謝!
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 ->()
}
由於我在序列表達式中,我相信它必須是產量。 – sst4460
事實上,它不能'返回!'。 –
你有沒有嘗試過使用Seq.unfold實現這個? – Ankur