Вы можете адаптировать решение Мартина так, чтобы данные распределялись между различными вызовами:
let fact =
let counter = ref 0 in
fun n ->
let rec fact = ... in
fact n
Идея состоит в том, чтобы преобразовать let fact = fun n -> let counter = ... in ...
в let fact = let counter = ... in fun n -> ...
: счетчик инициализируется один раз, а не при каждом вызовеfact
.
Классическим примером этого стиля является:
let counter =
let count = ref (-1) in
fun () ->
incr count;
!count
Однако учтите, что вы можете столкнуться с проблемами при наборе текста, если функция должна была быть полиморфной: let foo = fun n -> ...
всегдаОбобщенный в полиморфную функцию, let foo = (let x = ref ... in fun n -> ...)
не является, так как это было бы неправильно, поэтому foo
не будет иметь полиморфного типа.
Вы можете даже обобщить приведенный выше пример счетчика на counterfactory :
let make_counter () =
let count = ref (-1) in
fun () ->
incr count;
!count
Для каждого вызова make_counter ()
вы получаете новый счетчик, который является функцией, которая разделяет состояние по вызову, но состояние которой не зависит от предыдущих make_counter ()
созданий счетчика.