J'ai une fonction coûteuse comme ceci:Quelle est la manière idiomatique d'implémenter la mise en cache sur une fonction qui n'est pas une méthode struct?
pub fn get_expensive_value(n: u64): u64 {
let ret = 0;
for 0 .. n {
// expensive stuff
}
ret
}
Et il est appelé très souvent avec le même argument. C'est pur, ce qui signifie qu'il retournera le même résultat et pourra utiliser un cache.
S'il s'agissait d'une méthode struct, j'ajouterais un membre à la structure qui agit comme un cache, mais ce n'est pas le cas. Donc, mon option semble être d'utiliser une statique:
static mut LAST_VAL: Option<(u64, u64)> = None;
pub fn cached_expensive(n: u64) -> u64 {
unsafe {
LAST_VAL = LAST_VAL.and_then(|(k, v)| {
if k == n {
Some((n,v))
} else {
None
}
}).or_else(|| {
Some((n, get_expensive_value(n)))
});
let (_, v) = LAST_VAL.unwrap();
v
}
}
Maintenant, j'ai dû utiliser unsafe
. Au lieu de static mut
, je pourrais mettre un RefCell
dans un const
. Mais je ne suis pas convaincu que ce soit plus sûr - cela évite juste d'avoir à utiliser le bloc unsafe
. Je pensais à un Mutex
, mais je ne pense pas que cela m'amène à la sécurité des threads non plus.
Redessiner le code pour utiliser une struct pour le stockage n'est pas vraiment une option.
en double de [Comment puis-je créer un singleton global, mutable?] (Http://stackoverflow.com/questions/27791532/how- do-i-create-a-global-mutable-singleton). – Shepmaster
Ou vous pouvez modifier la signature de 'cached_expensive' pour accepter le cache comme un autre paramètre. – Shepmaster
Je ne pense pas que ce soit un doublon. Ma question concerne spécifiquement la mise en cache et, bien que mon point de départ soit un singleton global et mutable, c'est une bonne solution qui pourrait expliquer comment (par exemple) un "RefCell" ou "Mutex" pourrait améliorer cela, ou offrir une solution complète. alternative différente structurellement. –