Паскаль верен, но я думаю, что есть дополнительные объяснения, потому что есть ограничения.
OCaml реализует хвостовую рекурсию.Если возвращаемое значение функции полностью является результатом вызова функции, то вызов может быть оптимизирован.Рассмотрим эти два фрагмента кода:
let rec foo i =
i * foo(i-1)
и
let rec bar i j =
bar(i - 1, j * i)
Они оба вычисляют одну и ту же вещь (и ни одна из них не заканчивается)Однако первый вызовет переполнение стека, а второй - нет.Зачем?Потому что foo выполняет вычисления с результатом вызова функции.Это означает, что значение, которое мне нужно хранить в стеке, пока foo (i - 1) не вернется.С другой стороны, результат bar является результатом панели вызовов (i - 1, j * i) без изменений.Нет ничего, что нужно хранить в стеке.
Визуализируйте это таким образом.Допустим, мы начинаем с i = 3 (и j = 1).Foo будет выглядеть так:
foo(3)
3 * foo (2)
2 * foo (1)
, а bar будет выглядеть так:
bar (3, 1)
bar (2, 3)
bar (1, 6)