Sto cercando di implementare un elenco di smistamento funzione ricorsiva in coda in OCaml, e mi è venuta in mente il seguente codice:Coda-ricorsiva merge sort in OCaml
let tailrec_merge_sort l =
let split l =
let rec _split source left right =
match source with
| [] -> (left, right)
| head :: tail -> _split tail right (head :: left)
in _split l [] []
in
let merge l1 l2 =
let rec _merge l1 l2 result =
match l1, l2 with
| [], [] -> result
| [], h :: t | h :: t, [] -> _merge [] t (h :: result)
| h1 :: t1, h2 :: t2 ->
if h1 < h2 then _merge t1 l2 (h1 :: result)
else _merge l1 t2 (h2 :: result)
in List.rev (_merge l1 l2 [])
in
let rec sort = function
| [] -> []
| [a] -> [a]
| list -> let left, right = split list in merge (sort left) (sort right)
in sort l
;;
Eppure sembra che essa non è in realtà in coda ricorsiva, dal momento che si verifica un errore "Stack overflow durante la valutazione (ricorsione looping?)".
la prego di aiutarmi a individuare la chiamata non ricorsiva in coda in questo codice? Ho cercato parecchio, senza trovarlo. Cout è il let binding nella funzione sort
?
Oh, penso di capire; Grazie! Ma allora, come posso rendere la mia funzione ricorsiva? –
Potresti spiegare perché le continuazioni effettivamente rendono la funzione ricorsiva in coda? Oppure spostano semplicemente il processo di acquisizione dello stack frame dalla pila (potenzialmente traboccante) alla chiusura generata? – Dario
Hmmm, immagino che questo dovrebbe funzionare, ma non capisco cosa faccia la funzione k. Potresti spiegarcelo un po '? Molte grazie! L'ho provato, ma non risolve il problema dell'overflow ... Qualche idea del perché? –