Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Очень интересно. Но в данном случае ты взял заботу компилятора на себя и несмотря на то, что хорошо справился (
), я не думаю что этот подход разумен в общем случае.
LCR>let mk_index list_names =
LCR> let rec make_enum a b = if a > b then [] else a :: (make_enum (a+1) b) in
LCR> let list_index = (make_enum 0 ((List.length list_names) - 1)) in
LCR> let assoc_index_name = List.combine list_names list_index in
LCR> function name -> List.assoc name assoc_index_name ;;
LCR>"Функция mk_index возвращает функцию, которая принимает имя и вызывает List.assoc с этим именем и предварительно сформированным списком ассоциаций." (Пример взят из книжки "Developing apps in ocaml", пункт "Reading a database from a file").
make_enum : 'a -> 'a -> ['a], энергично порождает список, никаких вложенностей здесь не нужно.
Головная рекурсия — всего лишь красивый способ записи; элементарно переделывается в хвостовую
let make_enum a b =
let rec fwd c cs = if c > b then [] else fwd (c+1) (c::cs)
in
List.reverse (fwd a [])
;;
let make_enum a b =
let rec rew c cs = if c < a then [] else rew (c-1) (c::cs)
in
(rew b [])
;;
В первом случае мы инвертировали конструктор списка, во втором — инвертировали всю арифметику.
И между прочим, каррингуемость её нигде не востребована: во всех двух местах (в рекурсивном определении и ниже в list_index) она применяется с обоими аргументами. Можно было передавать кортеж.
Но это неважно.
Главное, что она не конструирует рекурсивную функцию (реализация которой может быть чем-то интерпретируемым — то ли AST, то ли шитым кодом), а вычисляет законченный объект — список чисел.
Внешняя функция
let mk_index list_names name =
let bla-bla-bla
in
List.assoc name assoc_index_name
;;
Зачем было помогать компилятору и заниматься каррингом функции mk_index вручную — не знаю.
Сама она этим не пользуется.
... << RSDN@Home 1.2.0 alpha rev. 655>>