-
Notifications
You must be signed in to change notification settings - Fork 20
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 an extract
macro which extracts values matched in a pattern
#495
Comments
extract
macro which extracts values matched in a patternextract
macro which extracts values matched in a pattern
For this particular example, it seems more natural that the library author is going to provide a impl TryFrom<Value> for char {
type Error = ...;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value {
Value::Char(c) => Ok(c),
_ => Err(...),
}
}
} then you can use the standard: let chars = arr.into_iter().filter_map(|x| x.try_into().ok()); |
sure, but that depends on the library author - the user has no control over whether the type implements let lifetimes = params.args.iter().filter_map(|arg| match arg {
GenericArg::Lifetime(lt) => Some(lt),
_ => None,
}); let tokens = node.preorder_with_tokens().filter_map(|event| match event {
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
_ => None,
}); plus, it's not always possible. consider the following enum: enum Value {
A(u64),
B(char),
C(u64),
} you can't have a edit: i got a little confused and edited the last example multiple times. i just woke up so please forgive my sillyness. |
I've sometimes wanted this, it's a fairly natural extension of the |
I'm not a fan of that motivating example, because to me the thing I'd expect is that it has impl Value {
fn char(self) -> Option<char> { … }
} Just like how there's |
You could configure rustfmt to let those be one-liners. |
I think it's worth comparing to the example written with enum Value {
Int(u64),
Float(f64),
Char(char),
}
fn main() {
use Value::*;
let arr = [Int(0), Char('a'), Float(0.0), Int(1), Char('b')];
let chars = arr
.into_iter()
.filter_map(|x| if let Char(c) = x { Some(c) } else { None });
for c in chars {
println!("got a character: {c}");
}
} The chain wraps onto three lines, but the |
I feel like One approach I do think would carry its weight (name and exact syntax extremely subject to bikeshed): let chars = arr
.into_iter()
.filter_map(opt_closure!(|Char(c)| c));
|
macro_rules! opt_closure {
(|$p:pat_param| $e:expr) => {
|x| if let $p = x { Some($e) } else { None }
};
} How is the "weight" carried by |
But the same could be said of // Note that matches! and extract! additionally support if guards
if let $pat = $arg { true } else { false }
if let $pat = $arg { Some($out) } else { None } |
We had evidence of The |
Proposal
Problem statement
it's not uncommon to pattern match on a value only to obtain the value of a binding. currently, the only way to do this is to either
match
on the value, useif let
or uselet else
. all these solutions involve multiple (~3) lines of code for a relatively simple operation, making code less concise.Motivating examples or use cases
Solution sketch
i propose an
extract
macro which extracts values matched in a pattern in a way similar to thematches
macro:the motivating example would then become:
Alternatives
as an alternative, just keep using
match
,if let
andlet else
, since they are able to get the job done. however, it's important to notice that they can also do whatmatches
does, but that does not makematches
undesirable or any less useful.Links and related work
searching crates.io for
extract macro
shows a crate implementing a macro with the exact same proposed syntax, but slightly different implementation.The text was updated successfully, but these errors were encountered: