我每晚都在使用Rust 1.15,并且根据std::io::Result<std::fs::DirEntry>
每个dir_contents_iterator
是对应一个文件还是在DirEntry
名为Err
的迭代器上编写一些代码。一个文件夹(let (dir_list, file_list): (Vec<std::io::Result<DirEntry>>, Vec<std::io::Result<DirEntry>>) =
dir_contents_iterator.partition(|entry_result| {
match entry_result {
Ok(entry) => {
entry
.file_type()
.and_then(|file_type| Ok(file_type.is_dir()))
.unwrap_or(false)
},
Err(_) => false
}
});
值已排序到文件列表中):
error[E0308]: mismatched types
--> src/main.rs:179:13
|
179 | Ok(entry) => {
| ^^^^^^^^^ expected reference, found enum `std::result::Result`
|
= note: expected type `&std::result::Result<std::fs::DirEntry, std::io::Error>`
= note: found type `std::result::Result<_, _>`
error[E0308]: mismatched types
--> src/main.rs:185:13
|
185 | Err(_) => false
| ^^^^^^ expected reference, found enum `std::result::Result`
|
= note: expected type `&std::result::Result<std::fs::DirEntry, std::io::Error>`
= note: found type `std::result::Result<_, _>`
此代码无法使用以下两个错误进行编译:
Err
我最终通过重写代码来解决我的问题,在文件和文件夹之间进行分区之前先将&Result
值分区。这允许从显示的代码中删除匹配,现在编译。但是为了理解,我仍然想知道为什么我的原始匹配分支臂期望Result
引用而不是接受Err(_) => false
,尤其是在第二个分支臂的情况下({{ 1}})甚至不使用该值!
Gitter如果我遗漏了任何有助于解释问题的细节。
答案 0 :(得分:1)
将此作为MCVE(您应该提供):
use std::fs::{self, DirEntry};
fn main() {
let dirs = fs::read_dir("/tmp").expect("Nope");
let (dir_list, file_list): (Vec<std::io::Result<DirEntry>>, Vec<std::io::Result<DirEntry>>) =
dirs.partition(|entry_result| {
match entry_result {
Ok(entry) => {
entry.file_type()
.and_then(|file_type| Ok(file_type.is_dir()))
.unwrap_or(false)
}
Err(_) => false,
}
});
}
然后您可以print out the type of the variable
dirs.partition(|entry_result| {
let () = entry_result;
false
});
表明entry_result
是&std::result::Result<std::fs::DirEntry, std::io::Error>
。
答案
为什么我的原始匹配分支机构需要
&Result
参考
是因为你给它一个&Result
!
为了完整性,您可以取消引用变量,然后引用组件:
match *entry_result {
Ok(ref entry) => {
这是多余的:
.and_then(|file_type| Ok(file_type.is_dir()))
因为它可以是map
:
.map(|m| m.is_dir())
还有一些清理工作:
use std::fs;
fn main() {
let dirs = fs::read_dir("/tmp").expect("Nope");
let (dir_list, file_list): (Vec<_>, Vec<_>) =
dirs.partition(|entry_result| {
entry_result.as_ref()
.ok()
.and_then(|entry| entry.file_type().ok())
.map(|ft| ft.is_dir())
.unwrap_or(false)
});
}
我的印象是
*
和ref
会互相撤消。
*
和ref
might undo each other,但这仅适用于相同值的情况。这里,我们是模式匹配,因此我们对取消引用的值采用&Result
和模式匹配。然后我们引用里面的值 Result
,所以没有任何东西被移动,但我们不会解除引用并重新引用相同的东西。