The idea is that you'd be able to implement Match<U>
for type T
and then you'd be able to include items of type U
within match statements.
For example, I could implement Match<&str> for String
and now, I can use &str
s when matching String
.
impl Match<&str> for String {
pub fn match(&self, value: &str) -> bool {
self.as_str() == value
}
}
// This is kind of a poor example since here you can just do my_string.as_str() at the top level,
// but you cannot do this when matching, for example, a struct/enum that might have a String or a Vec nested within it.
let my_value = String::from("Hello world!");
// We get this...
match my_string {
"Hello world!" => todo!(),
_ => todo!()
}
// Instead of this...
match my_string {
value if value.as_str() == "Hello world!" => todo!(),
_ => todo!()
}
// This can also let us match nested Vecs
impl<const N: usize, T> Match<[T; N]> for Vec<T> {
// implementation here
}
match my_vec {
[1, 2, 3] => {}
// Here, Match is implemented for both [i32; 2] and [i32; 3], meaning both can be matched
// even within the same statement
[1, 2] => {}
_ => todo!()
}
This trait would fix one of the greatest weaknesses of Rust's pattern matching system, but there are a few considerations here.
Matching does not work based on Rust values! Matching works based on patterns, which are just interpreted differently to Rust values. |
, when used on a Rust &str
, does not work -- but when used in the context of pattern matching, that means match either this, or that. This means that the Match<T>
trait signature will probably not be Match<T>
because T
is the type of a Rust value, and not a pattern matching token.
Perhaps the Match<T>
trait could use a new const-generic enum like below, instead of a type:
pub enum MatchToken<T> {
Str(String),
Num(f64),
Array(Vec<MatchToken>),
// etc . . .
}
However, with this approach you forgo the ability to implement Match
for other types like enums or structs.
Perhaps there is a better way to express this idea that simply has gone over my head, or some fatal flaw, but I still believe that it is important for Rust to implement basic matching for its std/alloc library types, and perhaps the best way to do this is by creating a generic interface that allows for extensible Rust match
ing (since its lack of extensibility is what got us here in the first place).