2012-11-30 12 views
5

So che questo è un po 'il contrario del problema che le persone stanno avendo quando fanno domande su un problema di overflow dello stack, ma se creo una funzione e la chiamo come segue, non ricevo mai errori e l'applicazione macina semplicemente un core della mia CPU fino a quando ho forzare lo spegnimento è:Perché la ricorsione infinita non ha colpito un'eccezione di overflow dello stack in F #?

let rec recursionTest x = 
    recursionTest x 

recursionTest 1 

Certo che posso cambiare questo in modo che in realtà fa qualcosa di simile:

let rec recursionTest (x: uint64) = 
    recursionTest (x + 1UL) 

recursionTest 0UL 

in questo modo posso ogni tanto mettere un punto di interruzione nel mio codice e vedere il valore di x sta salendo piuttosto rapidamente, ma non si lamenta ancora. A F # non interessa la ricorsione infinita?

risposta

8

La vostra funzione recursionTest è ricorsiva di coda, il che significa che tutte le chiamate ricorsive si verifica nella 'posizione di coda' vale a dire come l'ultima azione nella funzione. Ciò significa che il compilatore F # non ha bisogno di allocare un nuovo stack frame per le chiamate ricorsive, quindi non si verifica un overflow dello stack.

La ricorsione di coda è un caso specifico di tail call, la coda è chiamata a se stessa piuttosto che un'altra funzione.

+0

Grazie, ciò ha anche spiegato una domanda non menzionata sul motivo per cui VS non stava visualizzando più chiamate nella finestra dello stack di chiamate. – Amazingant

+1

In effetti credo che in questo caso il compilatore F # convertirà effettivamente il codice in un ciclo - non c'è in realtà alcuna ricorsione nel codice compilato. –

4

In generale, F # emette l'istruzione tailcall che quello .NET onori:

http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.tailcall(v=vs.95).aspx

In alcuni specifici casi semplici, come la vostra, F # riscrive programmi che utilizzano la ricorsione in programmi equivalenti utilizzando i cicli.

+0

Probabilmente l'avrei visto se avessi impiegato un minuto in più per lanciare l'app nel Disassembler IL o nel riflettore. Grazie per le informazioni aggiuntive sullo sfondo. – Amazingant

Problemi correlati