¿Cómo tomo prestado un RefCell , encuentro una clave y devuelvo una referencia al resultado?

Tengo un RefCell y quiero tomar prestada la tabla, encontrar una clave y devolver una referencia al resultado:

 use std::cell::RefCell; use std::collections::HashMap; struct Frame { map: RefCell<HashMap>, } impl Frame { fn new() -> Frame { Frame { map: RefCell::new(HashMap::new()), } } fn lookup(&'a self, k: &String) -> Option { self.map.borrow().get(k) } } fn main() { let f = Frame::new(); println!("{}", f.lookup(&"hello".to_string()).expect("blargh!")); } 

( patio de recreo )

Si RefCell el RefCell , todo funciona bien:

 struct Frame { map: HashMap, } impl Frame { fn lookup(&'a self, k: &String) -> Option { self.map.get(k) } } 

¿Cuál es la forma correcta de escribir la función de búsqueda sin copiar la cadena en la tabla hash?

Cuando RefCell prestado un RefCell , la referencia que obtiene tiene una vida útil más corta que la de RefCell . Esto se debe a que la vida útil de la referencia está restringida por el guardia devuelto por borrow() . Ese guardia asegura que nadie más pueda tomar una referencia mutable del valor hasta que se suelte el protector.

Sin embargo, estás tratando de devolver un valor sin mantener a un guardia con vida. Si Frame tenía un método que tomaba un argumento &self pero intentaba mutar el mapa (lo cual es posible con RefCell – si no necesitas hacer eso, entonces RefCell el RefCell y escribe y RefCell sobre los métodos que mutan el mapa), podrías destruir accidentalmente una String que alguien más hace referencia. ¡Ese es exactamente el tipo de errores que el inspector de préstamos fue diseñado para informar!

Si los valores del mapa son efectivamente inmutables (es decir, su tipo no permitirá la mutación de los valores del mapa), también podría envolverlos en un Rc en su mapa. Por lo tanto, podría devolver un clon de Rc (esto solo clona el puntero contado de referencia, no la cadena subyacente), lo que le permitiría liberar el préstamo en el mapa antes de regresar de la función.

 struct Frame { map: RefCell>> } impl Frame { fn lookup(&self, k: &String) -> Option> { self.map.borrow().get(k).map(|x| x.clone()) } }