Я пытаюсь реализовать хвостовую рекурсию список сортировки функции в OCaml, и я придумал следующий код:Tail-рекурсивная сортировка слиянием в 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
;;
Тем не менее, кажется, что это на самом деле не является хвостовым рекурсивным, так как я сталкиваюсь с ошибкой «Переполнение стека во время оценки (циклическая рекурсия?)».
Не могли бы вы помочь мне обнаружить не хвостовой рекурсивный вызов в этом коде? Я много искал, не найдя его. Cout это будет привязка let в функции sort
?
О, я думаю, я понимаю; благодаря! Но тогда, как я могу сделать свою функцию рекурсивной? –
Не могли бы вы объяснить, почему продолжение действительно делает функцию хвостовой рекурсивной? Или они просто перемещают процесс захвата стекового кадра из (потенциально переполненного) стека в сгенерированное закрытие? – Dario
Хммм, я думаю, это должно сработать, но я действительно не понимаю, что делает функция k. Не могли бы вы немного объяснить это? Большое спасибо! Я протестировал его, хотя он не решает проблему переполнения ... Любая идея почему? –