/ / Пам'ять хвостових викликів, оптимізовані рекурсивні функції у F # [дублікат] - f #, запам'ятовування

Запам'ятовування кінцевого дзвінка оптимізовані рекурсивні функції в F # [дублікат] - f #, memoising

Можливі дублікати:
Поєднайте запам'ятовування та рекурсію хвоста

Отже, наступним є код, який я написав, хвостовий виклик оптимізований за допомогою змінної накопичення

let rec counter init count =
if init = 1 then count + 1 else
match init with
| Even value -> (counter (value/2)  (1 + count))
| Odd value -> (counter ((3 * value) + 1) (count+1))

let SeqBuilder (initval:int) : int =
counter initval 0

Як це запам'ятати? Проблема, з якою я зіткнувся, коли я намагався запам’ятати, це те, що рекурсивний виклик повинен перейти до об'єкта запам'ятовування, тому у вас повинен бути… рекурсивний об’єкт?

Або це набагато простіше, і я просто недосвідчений?

Відповіді:

3 для відповіді № 1

F # дозволяє визначити a рекурсивне значення (наприклад, рекурсивний об'єкт, про який ви згадали), тож якщо у вас є memoize2 функція робити запам'ятовування (приймаючи функцію з двох аргументів - зробити її сумісною з вашою counter), тоді ви можете написати:

let rec counter = memoize2 (fun init count ->
if init = 1 then count + 1 else
match init with
| Even value -> (counter (value/2) (1 + count))
| Odd value -> (counter ((3 * value) + 1) (count+1)) )

Такі рекурсивні посилання можуть бути небезпечними, тому F # вставляє кілька перевірок виконання. Це також дає попередження FS0040 повідомити вас про це, але в цьому випадкурекурсія правильна (проблема може виникнути, якщо під час ініціалізації звертався до рекурсивної посилання - тут ми використовуємо її лише пізніше, коли функція вже оголошена, тому все добре). Ви можете відключити попередження, додавши #nowarn "40".