I'm a hobbyist that is slowly going through the proc macro workshop, just for fun.
I have the first handful of tests on the Builder project working, but I keep running into a pattern that makes me think that there is a more idiomatic alternative that I'm missing: setting an Optional<T> with layers of match and if let that result in layers and layers of else { None }.
It seems that if trying to match target == 42 that is embedded several layers deep in some struct with mixed Optionals and sequences etc. on the way down that there is probably a better way to do several matches without having to keep saying else { None } for every alternative path. Right?
I keep thinking that there is probably some way to .map or .and_then my way to a cleaner approach, but the sequences and match guards seem to keep interfering with chaining them, and AFAICT there's no way around that.
One way (that I can think of now at midnight) I've handled those cases is by writing a fallible closure inside the infallible function to able to use the ? operator (this is an example from my recent answer to a thread on r/learnrust which is why I remember it) :
fn extract_name(path: &Path) -> &str {
static PATTERN: Lazy<Regex> =
Lazy::new(|| Regex::new(...).unwrap());
// this closure is fallible, so it can make use of `?`
let capture = || {
let stem = path.file_stem()?.to_str()?;
let caps = PATTERN.captures(stem)?;
Some(caps.get(1)?.as_str())
};
capture().unwrap_or("untitled")
}
I've also done it here for something public a bit a more involved. I think I've first seen that last year in a tweet ? It probably should belong in Rust Patterns.
Thanks for the suggestion! I was about to propose something like this but you beat me to it.
For some reason I thought it would need to be a standalone function, but a closure would be just dandy.
EDIT: Although on stable I guess the ? operator won't really work for Optional unless I convert the None (I think there is a NoneError coming in unstable, right?).
Perhaps I could make something like a closure with early returns for the happy path and just a None at the end, and add some semicolons to have all the other paths return () everywhere else?
Wow, my mind is blown. It looks my first commit of Rust code was March 21, 2019. That means it's been two years that I could have been using? on Option and somehow didn't figure that out. That makes for a lot of totally unnecessary usages of <Option<T>>.ok_or_else(|| LetMeUseQuestionmarkError)?!
How could I have missed that.
Thank you. That makes the path of refactoring this into a closure or function to leverage early returns much more obvious.