-
-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new api similar to try_get_with
, but return Option
rather than Result
?
#184
Comments
Thank you for offering contribution! I like the idea of adding such API. The name Actually, when I saw your idea, I wondered if we could make I played around with my idea and came up with the following code using // As of today (late 2022), Rust Nightly and the following feature is required:
#![feature(try_trait_v2)]
use std::{
convert::Infallible,
ops::{ControlFlow, Try},
sync::Arc,
};
#[derive(Default)]
struct Cache<K, V>(std::collections::HashMap<K, V>);
impl<K, V> Cache<K, V> {
// try_get_with that is generic over Result, Option, ControlFlow, etc.
fn try_get_with<F, R>(&mut self, _key: K, init: F) -> R
where
F: FnOnce() -> R,
R: Try<Output = V>,
{
match init().branch() {
ControlFlow::Continue(v) => R::from_output(v),
ControlFlow::Break(r) => R::from_residual(r),
}
}
// Problem: Cannot encode the following requirements into the type.
//
// When F's concrete return type is Result<V, E> or ControlFlow<E, V>,
// - E: Send + Sync + 'static is required.
// - try_get_with's return type must be Result<V, Arc<E>> or ControlFlow<Arc<E>, V>
// instead of Result<K, E> or ControlFlow<E, K>.
// This will emulate today's try_get_with.
#[allow(dead_code)]
fn try_get_with_r<F, E>(&mut self, key: K, init: F) -> Result<V, Arc<E>>
where
F: FnOnce() -> Result<V, E>,
E: Send + Sync + 'static,
{
self.try_get_with(key, init).map_err(Arc::new)
}
}
fn main() {
use ControlFlow as CF;
let mut cache: Cache<i32, String> = Cache::default();
let ok = "ok".to_string();
let err = "err".to_string();
// Success cases
// Result<String, Infallible>
assert_eq!(
cache.try_get_with(0, || Ok(ok.clone()) as Result<_, Infallible>),
Ok(ok.clone())
);
// Option<String>
assert_eq!(cache.try_get_with(0, || Some(ok.clone())), Some(ok.clone()));
// ControlFlow<Infallible, String>
assert_eq!(
cache.try_get_with(0, || CF::Continue(ok.clone()) as CF<Infallible, _>),
CF::Continue(ok.clone())
);
// Failure cases
// Result<String, String>
assert_eq!(cache.try_get_with(0, || Err(err.clone())), Err(err.clone()));
// Option<String>
assert_eq!(cache.try_get_with(0, || None), None);
// ControlFlow<String, String>
assert_eq!(
cache.try_get_with(0, || CF::Break(err.clone())),
CF::Break(err.clone())
);
} |
Thanks @tatsuya6502 for the feedback. I will spend sometime to look into adding the new API. I also spend sometime to look into the problem you mentioned in the previous thread. I am not sure if I fully understand what you want to achieve. Base on my understanding. if we want to solve the problem you mentioned, we need some sort of "conditional" compilation/type, basically tell compiler, hey if the |
I feel so too. So adding
If the If the |
Got it. Thanks for your explaination. |
Thank you! You might want to start reading the code for an internal method Line 1161 in 4ac7d8c
Then read the code of moka/src/sync/value_initializer.rs Lines 21 to 27 in 4ac7d8c
moka/src/sync/value_initializer.rs Lines 11 to 13 in 4ac7d8c
Notice I think you want to add something like |
Thanks for your comments & suggestions. That's very helpful. Will definitely look into it. |
Thanks for the great work on the library!
I am using the library in one of the project that I am working on and I feel some apis similar to try_get_with, but instead of the function return
Result<V,E>
, having Function returnsOption<V>
would be more "ergonomics".Just want to know if you are have any objections of adding such APIs. Maybe something like "optional_get_with"? Happy to contribute if you are okay with it. Thanks
The text was updated successfully, but these errors were encountered: