Duplicar Possível:
Combinar memoização e recursão da cauda
Então, o seguinte é o código que escrevi, chamada final otimizada usando uma variável de acumulação
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
Como memorizo isso? o problema que encontrei quando tentei memorizar é que a chamada recursiva tem que ir para o objeto memorizar, então você precisa ter um ... objeto recursivo?
Ou é muito mais simples e sou apenas inexperiente?
Respostas:
3 para resposta № 1F # permite definir um valor recursivo (como objeto recursivo que você mencionou), se você tiver memoize2
para executar a memorização (assumindo uma função de dois argumentos - para torná-la compatível com o seu counter
), então você pode escrever:
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)) )
Referências recursivas como essa podem ser perigosas; portanto, o F # insere algumas verificações em tempo de execução. Também dá um aviso FS0040
para notificá-lo sobre isso, mas, neste caso, orecursão está correta (um problema pode ocorrer se a referência recursiva for acessada durante a inicialização - aqui a usamos apenas mais tarde, quando a função já está declarada, para que tudo esteja bem). Você pode desativar o aviso adicionando #nowarn "40"
.