Вы всегда передаете пустой список как reversed
и добавляете первый элемент ввода в front рекурсивного результата.
Давайте пройдемся по небольшому тестовому сценарию - реверсирование [1;2]
.
Это helper [1;2] []
и
helper [1;2] []
—> if [1;2] = [] then [] else List.hd [1;2] :: (helper (List.tl [1;2]) [])
-> List.hd [1;2] :: (helper (List.tl [1;2]) [])
—> 1 :: (helper [2] [])
—> 1 :: (if [2] = [] then [] else List.hd [2] :: (helper (List.tl [2]) []))
—> 1 :: (List.hd [2] :: (helper (List.tl [2]) []))
—> 1 :: 2 :: (helper [] [])
—> 1 :: 2 :: if [] = [] then [] else List.hd [] :: (helper (List.tl []) [])
—> 1 :: 2 :: []
—> [1;2]
Рассмотрим колоду карт.
Возьмите верхнюю карту и положите ее на стол.
Затем возьмите вторую карту и положите ее поверх первой карты.
Если вы продолжите это делать, пока первая колода не опустеет, у вас будет "новая колода, которая находится в обратном порядке от первой.
Точка вспомогательной функции в точности соответствует этому принципу - вы можете повернуть элементы, «переместив» их с remainder
на reversed
, ирекурсивный вызов должен быть «хвостовым вызовом», то есть он просто возвращает результат, ничего не делая с ним.
let rec helper remainder reversed =
if remainder = []
then reversed
else helper (List.tl remainder) (List.hd remainder :: reversed)
затем
helper [1;2] []
—> if [1;2] = [] then [] else helper [2] [1]
—> if [2] = [] then [1] else helper [] [2;1]
—> if [] ≈ [] then [2;1] else helper [] ...
—> [2;1]