Как отмечает Виктор, вы не можете взять рекурсивную функцию и «внедрить» некоторое поведение в место, где происходит рекурсивный вызов (потому что функция уже завершена).Вы должны будете предоставить некоторую точку расширения для этого.В решении Виктора это делается путем использования функции, которая будет вызываться рекурсивно, в качестве аргумента, что является наиболее общим решением.
Более простой вариант - использовать F # значение рекурсии , которое позволяет вамсоздать значение функции и использовать его в своем объявлении.Вы можете использовать это для создания рекурсивной функции, вызывая другую функцию, которая добавляет некоторое поведение к функции (например, подсчет):
let rec factorial = counted (fun x ->
if x = 0 then 1
else x * (factorial (x - 1)) )
factorial 10
Внутри лямбда-функции мы можем напрямую получить доступ к определяемой нами функции,поэтому нет необходимости, чтобы передаваемая функция вызывалась рекурсивно в качестве дополнительного параметра.Функция counted
просто оборачивает данную функцию f
и добавляет некоторые функциональные возможности:
let counted f =
let count = ref 0
(fun x ->
count := !count + 1;
printfn "call: %d" (!count)
f x)
Благодаря рекурсии значения функциональность будет добавлена к функции factorial
(и поэтому, когда он вызывает себя, он вызывает версию с добавленной поддержкой подсчета).