Ho appena scritto un piccolo programma Rust che calcola i numeri di Fibonacci e memoizza il calcolo. Funziona, ma sono un po 'confuso sul perché, specialmente sulla chiamata ricorsiva. (E 'anche probabilmente non è idiomatica.)Perché non è necessario prestare esplicitamente una variabile mutuata e mutuata?
Ecco il programma:
use std::collections::HashMap;
fn main() {
let n = 42; // hardcoded for simplicity
let mut cache = HashMap::new();
let answer = fib(n, &mut cache);
println!("fib of {} is {}", n, answer);
}
fn fib(n: i32, cache: &mut HashMap<i32,i32>) -> i32 {
if cache.contains_key(&n) {
return cache[&n];
} else {
if n < 1 { panic!("must be >= 1") }
let answer = if n == 1 {
0
} else if n == 2 {
1
} else {
fib(n - 1, cache) + fib(n - 2, cache)
};
cache.insert(n, answer);
answer
}
}
Ecco come ho capito quello che sta succedendo:
- In
main
,let mut cache
significa "Voglio essere in grado per mutare questa hashmap (o riassegnare la variabile) ". - Quando
main
chiamafib
, passa&mut cache
per dire "Ti sto prestando questo e ti è permesso di mutarlo". - nella firma di
fib
,cache: &mut Hashmap
significa "mi aspetto di essere prestato un HashMap mutabile - di prendere in prestito con il permesso di mutare"
(Si prega di correggermi se sbaglio.)
Ma quando ricorre fib
, chiamando fib(n -1, cache)
, non ho bisogno di usare fib(n -1, &mut cache)
, e ottengo un errore se lo faccio: "non posso prendere in prestito la variabile locale immutabile cache
come mutabile". Eh? Non è una variabile locale immutabile, è un mutuo mutevole - giusto?
Se provo fib(n - 1, &cache)
, ottengo un errore di leggermente diverso:
error: mismatched types:
expected `&mut std::collections::hash::map::HashMap<i32, i32>`,
found `&&mut std::collections::hash::map::HashMap<i32, i32>`
che sembra che sta dicendo "Mi aspettavo un riferimento mutevole e ottenuto un riferimento a un riferimento mutabile".
So che fib
è in prestito nella chiamata ricorsiva perché se ha dato la proprietà, non poteva chiamare in seguito cache.insert
. E so che questo non è un caso speciale per la ricorsione, perché se definisco lo fib2
in modo che sia identico allo fib
, posso farli recitare l'uno con l'altro e funziona perfettamente.
Perché non è necessario prestare esplicitamente una variabile mutuata in prestito?
È possibile passare la proprietà e la funzione restituire una tupla con la risposta e la cache: [PlayPen] (http://is.gd/tUadZ0) –