В вашем коде только один рекурсивный вызов, и он находится в хвостовой позиции. Поэтому я бы сказал, что ваша функция хвостовая рекурсивная.
Она создает довольно большие вычисления в аргументе sc
. Тем не менее, вызов sc
также находится в хвостовой позиции. В моих тестах функция работала для очень больших списков без исчерпания пространства стека.
Если я опробую вашу функцию на двух копиях очень длинного списка (100 000 000 элементов), она успешно завершится (после довольно долгоговремя). Это наводит меня на мысль, что это действительно хвостовая рекурсия.
Вот сеанс с длинным списком:
# let rec zip_tr fc sc l1 l2 = . . . ;;
val zip_tr :
(int -> 'a) -> (('b * 'c) list -> 'a) -> 'b list ->
'c list -> 'a = <fun>
# let rec mklong accum k =
if k <= 0 then accum
else mklong (k :: accum) (k - 1);;
val mklong : int list -> int -> int list = <fun>
# let long = mklong [] 100_000_000;;
val long : int list =
[1; 2; 3; 4; 5; ...]
# let long_pairs =
zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) long long;;
val long_pairs : (int * int) list =
[(1, 1); (2, 2); (3, 3); (4, 4); (5, 5); ...]
# List.length long_pairs;;
- : int = 100000000
Если вы измените свой код так, чтобы вызов sc
не былхвостовой вызов:
zip_tr fc (fun l -> (h1, h2): sc l) t1 t2
Он генерирует результат в обратном порядке, но также не работает для длинных списков:
# zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) [1;2] [3;4];;
- : (int * int) list = [(2, 4); (1, 3)]
# zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) long long;;
Stack overflow during evaluation (looping recursion?).
Я недостаточно знаю о генерации кода OCamlчтобы объяснить это подробно, но это предполагает, что ваш код действительно является рекурсивным. Однако возможно, что это зависит от реализации замыканий. Для другой реализации, возможно, сгенерированные вычисления для sc
будут занимать большой объем стека. Может быть, это то, что вам говорят.