Rust 如何与选项进行模式匹配<;字符串>;?
我可以直接在Rust中匹配Rust 如何与选项进行模式匹配<;字符串>;?,rust,pattern-matching,Rust,Pattern Matching,我可以直接在Rust中匹配字符串: let a = "hello".to_string(); match &a[..] { "hello" => { println!("Matches hello"); } _ => panic!(), } 如果我有一个选项类型,它将失败: match Some(a) { Some("hello") => { println!("Matches some hello")
字符串
:
let a = "hello".to_string();
match &a[..] {
"hello" => {
println!("Matches hello");
}
_ => panic!(),
}
如果我有一个选项类型,它将失败:
match Some(a) {
Some("hello") => {
println!("Matches some hello");
}
_ => panic!(),
}
因为类型不匹配:
错误[E0308]:类型不匹配
-->src/main.rs:5:14
|
5 |一些(“你好”)=>{
|^^^^应为结构'std::string::string',找到引用
|
=注意:应为'std::string::string'类型`
找到类型`&'static str`
我不能做[…]
把戏,因为我们有一个选项
到目前为止,我得出的结论是:
match Some(a) {
Some(b) => match (&b[..]) {
"hello" => {
println!("Matches some, some hello");
}
_ => panic!(),
},
None => panic!(),
}
这是有效的,但它的冗长可怕
在本例中,我的代码只是一个示例。我既不能控制字符串
的创建,也不能控制某些(字符串)
的创建-因此,我不能像在示例中那样实际更改此类型
还有其他选择吗?
您无法在std::String
上进行匹配,正如您所发现的,只能在&str
上进行匹配。嵌套模式匹配有效,因此如果可以在&str
上进行匹配,则可以在选项上进行匹配,但仍然不能在选项上进行匹配
在工作示例中,通过执行&a[…]
,将std::String
转换为&str
。如果要匹配选项,则必须执行相同的操作
一种方法是使用嵌套匹配:
match a {
Some(ref s) => match &s[..] {
"hello" => /* ... */,
_ => /* ... */,
},
_ => /* ... */,
}
但是如果“否则”的代码是相同的,那么你就必须复制它,而这通常不是很好
相反,您可以使用映射
函数将选项
转换为选项
并进行匹配。但是,映射
会消耗调用它的值,将其移动到映射函数中。这是一个问题,因为您希望引用字符串,如果将其移动到mappi中,则无法执行此操作ng函数。首先需要将选项
转换为选项
,并映射到该选项上
因此,您最终得到了a.as_ref().map(|s |/*s是type&String*/&s[…])
。然后您可以在这一点上进行匹配
match os.as_ref().map(|s| &s[..]) {
Some("hello") => println!("It's 'hello'"),
// Leave out this branch if you want to treat other strings and None the same.
Some(_) => println!("It's some other string"),
_ => println!("It's nothing"),
}
这是已知的锈迹模式的局限性
方法调用(包括运算符的内部方法,如==
)会根据需要自动调用.deref()
,因此字符串
会自动转换为&str
,以便与文本进行比较
另一方面,这些模式在比较中相当直白,并且发现String
和&str
是不同的
有两种解决方案:
在匹配之前,将选项更改为选项:一些(a).as_deref()
。as_deref()
是as_ref()
的组合,使选项(防止移动)和deref()
/as_str()
,然后明确地将其引用为&str
使用match-guard:match Some(a){Some(ref s)if s==“hello”=>…}
Some(ref s)
匹配任何String
,并将其捕获为s:&String
,然后可以在if
保护中进行比较,该保护执行通常的灵活强制操作
另见:
在某些情况下,您可以使用unwrap\u或
将选项::None
替换为预定义的&str
,您不希望以任何特殊方式进行处理
我用它来处理用户输入:
let args: Vec<String> = env::args().collect();
match args.get(1).unwrap_or(&format!("_")).as_str() {
"new" => {
print!("new");
}
_ => {
print!("unknown string");
}
};
从Rust 1.40开始,您现在可以在选项
上调用As_deref
,将其转换为选项
,然后在其上进行匹配:
match args.nth(1).as_deref(){
一些(“帮助”)=>{}
一些(s)=>{}
无=>{}
}
我发现这是因为它是。这很好——我更喜欢1,因为它不太详细,因为我想匹配多个字符串。但是,我发现它令人困惑。为什么我们可以在选项上对单个值创建迭代器
?为什么我们可以在映射
返回时匹配单个值?这不是迭代器
类型吗?这里的.map()
根本不是迭代器。它是选项
上的一个辅助方法,允许您在部分
时更改它,如果无
则什么也不做。啊,请原谅我的无知。完全误解了rust doc的选项。是的,您是对的--“map”==使用与集合相同的名称将一个选项映射到另一个选项。点1的替代选项可以是Some(a)。as_deref()
您可以通过更改引用/展开顺序来避免临时分配:选项。as_deref().unwrap_或(“未处理的字符串”)
。也可以字符串::from(“\ux”)
生成的代码远远少于动态格式化机制。
let option = Some("hello");
match option.unwrap_or(&format!("unhandled string").as_str()) {
"hello" => {
println!("hello");
}
_ => {
println!("unknown string");
}
};