Diciamo che si dispone di una funzione ricorsiva definita in un blocco let:C'è un modo più semplice per memoizzare un let fn ricorsivo?
(let [fib (fn fib [n]
(if (< n 2)
n
(+ (fib (- n 1))
(fib (- n 2)))))]
(fib 42))
Questo può essere trasformato meccanicamente di utilizzare memoize
:
- Wrap forma
fn
in una chiamata amemoize
. - Sposta il nome della funzione come primo argomento.
- Passa la funzione in se stessa ovunque venga chiamata.
- Ricollegare il simbolo della funzione per fare lo stesso utilizzando
partial
.
Trasformare il codice di cui sopra porta a:
(let [fib (memoize
(fn [fib n]
(if (< n 2)
n
(+ (fib fib (- n 1))
(fib fib (- n 2))))))
fib (partial fib fib)]
(fib 42))
Questo funziona, ma si sente troppo complicato. La domanda è: c'è un modo più semplice?
In questo caso è necessario utilizzare il TCO (utilizzando 'loop' come Clojure non ha TCO nella definizione comune). – Hauleth
@hauleth Questa domanda riguarda come applicare la memoizzazione a una funzione ricorsiva arbitraria definita nel contesto di un blocco let. Questa particolare formulazione di Fibonacci ricorsiva dell'albero viene utilizzata solo perché è un semplice esempio ben noto che illustra i vantaggi della memoizzazione. Sicuramente, il calcolo stack-friendly dei numeri di Fibonacci avrebbe un approccio diverso. –