我正在尝试:
Option<&str>
,然后从其中构建一个PathBuf
。None
,则打印一些消息,然后返回。use std::path::PathBuf;
fn it_works() {
let path_str = Some("/tmp/abc");
let path = path_str.map(|s| PathBuf::from(s));
if !path.map_or(false, |p| p.is_dir()) {
match path {
Some(p) => println!("The folder {:?} is not a directory!", p),
None => println!("The repository folder is not set!"),
}
return;
}
}
上述代码段中的模式匹配无效,因为该值已在map_or
组合器中移动:
error[E0382]: use of moved value
--> src/lib.rs:8:18
|
5 | let path = path_str.map(|s| PathBuf::from(s));
| ---- move occurs because `path` has type `std::option::Option<std::path::PathBuf>`, which does not implement the `Copy` trait
6 | if !path.map_or(false, |p| p.is_dir()) {
| ---- value moved here
7 | match path {
8 | Some(p) => println!("The folder {:?} is not a directory!", p),
| ^ value used here after move
我可以做这样的事情,但是由于unwrap
和多个if
子句,感觉不太“习惯”:
let path_str = Some("/tmp/abc");
let path = path_str.map(|s| PathBuf::from(s));
if path.is_none() {
println!("The repository folder is not set!");
return;
}
let p = path.unwrap();
if !p.is_dir() {
println!("The folder {:?} is not a directory!", p);
}
有更好的解决方案吗?
答案 0 :(得分:1)
如果.map(...)
中的闭包(或Option
上的任何类似函数)不需要对该选项中的值拥有所有权(即,只需要引用该值),则可以始终使用option.as_ref()
或option.as_mut()
将&Option<T>
或&mut Option<T>
变成Option<&T>
或Option<&mut T>
。然后调用.map()
不会拥有所有权,因为引用是可复制的,因此它只是复制到提供的闭包中。
考虑到这一点,您的代码将被修改为:
fn it_works() {
let path_str = Some("/tmp/abc");
let path = path_str.map(|s| PathBuf::from(s));
if !path.as_ref().map_or(false, |p| p.is_dir()) {
// ^^^^^^^^^ using .as_ref() here
// ^^^ now p is a '&PathBuf' instead of 'PathBuf'
match path {
// ^^^^ we didn't take ownership so compiler doesn't complain here
Some(p) => println!("The folder {:?} is not a directory!", p),
None => println!("The repository folder is not set!"),
}
return;
}
}
答案 1 :(得分:0)
PathBuf
实现了FromStr
特征,因此您可以将其与强大的模式匹配结合使用。
fn it_works() {
use std::path::*;
use std::str::FromStr;
let path_str: Option<&str> = Some("/tmp/abc");
match path_str.map(PathBuf::from_str) {
Some(Ok(p)) => if !p.is_dir() {},
Some(Err(e)) => {}
None => {}
};
}