Я написал простую функцию для репликации каждого элемент в списке заданное количество раз.
let rec replicate l n =
let rec f l n acc =
match l with
|[]->acc
|x::xs->f xs n (let rec h e n acc = if n = 0 then acc else h e (n-1) (e::acc) in h x n acc)
in List.rev (f l n [])
Это работает, поскольку я вызываю f
и устанавливаю его аккумулятор на результат вспомогательного метода h
Но почему следующий метод не работает?
let rec replicate l n =
let rec f l n acc =
match l with
|[]->acc
|x::xs->(let rec h e n acc = if n = 0
then f xs n acc else h e (n-1) (e::acc)
in h x n acc)
in f l n [];;
Здесь я вызываю внешнюю функцию f
в случае n=0
.
Вот результаты для одного и того же вызова с двумя функциями:
Есть еще одна закрытая скобка, которой там быть не должно: let rec h e n acc = (if n = 0)
Во второй строке
let rec h e n acc =
if n = 0 then f xs n acc
else h e (n-1) (e::acc)
in h x n acc
вы вызываете f xs n acc
с n=0
, а не с начальным значением n
.
Общий совет: лучше не вкладывать определения рекурсивных функций. Действительно, это ограничивает сложность вашего потока управления функциями. Например, с
let rec repeated_append n x l =
if n = 0 then l
else repeated_append (n-1) x (x::l)
let replicate n l =
let rec replicate_aux n acc l =
match l with
| [] -> List.rev acc
| x::xs-> replicate_aux n (repeated_append n x acc) xs
in
replicate_aux n [] l
Я уверен, что рекурсивные функции repeated_append
и replicate_append
вызывают только себя в своем теле. В частности, нет возможности h
вызова replicate
или f
, что упрощает чтение функции.
Учитывая repeated_append
, вы также можете определить replicate
просто как: let replicate n l = List.(l |> map (fun x -> repeated_append n x []) |> flatten)
Если мы используем функции из модуля List
, лучше использовать List.concat_map
напрямую.
Справедливо. Рано утром для меня. Также застрял на более старой версии OCaml на этой рабочей станции.
Независимо от вопроса о наиболее оптимальной функции stdlib, ваш пример является хорошей иллюстрацией того, что определение полезных вспомогательных функций упрощает написание более сложных функций путем объединения небольших функций.
Вторая функция имеет синтаксическую ошибку