Böyle pahalı bir işlevi vardır:Yapılandırma yöntemi olmayan bir işleve önbelleğe almanın deyimsel yolu nedir?
pub fn get_expensive_value(n: u64): u64 {
let ret = 0;
for 0 .. n {
// expensive stuff
}
ret
}
Ve aynı argümanı ile çok sık çağrılır. Bu saf, yani aynı sonucu döndürecek ve bir önbellekten faydalanabileceği anlamına gelir.
Bu bir yapı yöntemi olsaydı, önbellek gibi davranan yapıya üye eklerdim, ancak değil. Yani benim seçenek statik kullanmak gibi görünüyor: Şimdi
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
}
}
, ben unsafe
kullanmak zorunda kalmıştım. static mut
yerine, bir RefCell
bir const
içine koyabilirsiniz. Ama ben daha güvenli olduğuna inanmıyorum - sadece unsafe
bloğunu kullanmaktan kaçınıyor. Bir Mutex
'u düşündüm, ama bunun da iplik güvenliği sağlayacağını sanmıyorum.
Depolama için bir yapı kullanılacak kodun yeniden tasarlanması gerçekten bir seçenek değildir.
Yinelenen içinde "küresel" beyanı verir [I küresel, değişken singleton yaratabilirim?] (http://stackoverflow.com/questions/27791532/how- do-i-create-a-küresel-değişken-singleton). – Shepmaster
Veya önbelleği başka bir parametre olarak kabul etmek için 'cached_expensive' imzasını değiştirebilirsiniz. – Shepmaster
Bunun bir kopya olduğunu sanmıyorum. Benim sorum özellikle önbelleğe alma ile ilgilidir ve başlangıç noktam küresel, değişken bir tekil olsa da, tesadüfi ve iyi bir çözüm (örneğin) bir "RefCell" veya "Mutex" in bunu nasıl daha iyi hale getirebileceğini veya tamamen nasıl olabileceğini açıklayabilir yapısal olarak farklı bir alternatif. –