2017-01-02 1 views
0

야간에 녹 1.15를 사용 중이며 std::io::Result<std::fs::DirEntry> 이상의 코드가 있습니다. 각각의 DirEntry이 파일 또는 폴더에 해당하는지 여부에 따라 파티션을 지정하려고합니다 (이름은 dir_contents_iterator)결과를 사용할 때 예상 결과 및 결과

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 값)와 e 파일과 폴더를 분할하기 전에 먼저 Err 값을 분할합니다. 이렇게하면 표시된 코드에서 일치 항목을 제거하고 컴파일 할 수 있습니다. 그러나 이해를 돕기 위해, 원래 제 시합의 브랜치 팔이 Result을 받아들이 기보다는 &Result 참조를 기대하는지, 특히 값을 사용하지 않는 두 번째 브랜치 팔 (Err(_) => false)의 경우를 알고 싶습니다. !

Here's the problem code in the context of the project I'm working on 문제를 설명하는 데 도움이되는 세부 정보를 빠뜨린 경우를 대비하여 (귀하가 제공 한한다)를 MCVE으로 이것을 사용

답변

1

:

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, 
      } 
     }); 
} 

할 수 있습니다 다음 entry_result&std::result::Result<std::fs::DirEntry, std::io::Error> 것을 보여준다 print out the type of the variable

dirs.partition(|entry_result| { 
    let() = entry_result; 
    false 
}); 

.

그래서

에 대한 대답은 왜 내 원래의 일치의 지점 팔은 그것을 &Result을주는 때문에

가있는 &Result 참조를 기대합니다!

match *entry_result { 
    Ok(ref entry) => { 

이 중복 : 완성도를 들어


, 당신은하고 변수를 역 참조 후 구성 요소를 참조 할 수 있습니다

.map(|m| m.is_dir()) 
:

.and_then(|file_type| Ok(file_type.is_dir())) 

를 그냥 map 할 수

그리고 좀 더 정리 :

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 서로 단지를 취소 할 것이라는 인상이었다.

*refmight undo each other,하지만 그들은 같은 값에 적용한다면 그에만 적용됩니다. 여기서는 패턴 일치이므로 &Result을 사용하고 역 참조 된 값과 패턴 일치를 취합니다. 그런 다음 Result 값을 참조하므로 아무 것도 이동하지 않지만 같은 참조를 역 참조 및 다시 참조하지는 않습니다.

+0

당신은 방금 일치 항목에서'* entry_result'를 사용하고 나서 match arm에서'ref entry'를 사용하여 마음을 아프게했습니다. 나는 그런 식으로 일한다는 것을 전혀 몰랐습니다. 나는'*'와'ref '가 서로를 원상태로 돌릴 것이라는 인상을 받았다. – user3791276

+0

@ user3791276 님이 1 비트를 더 추가했습니다. – Shepmaster

관련 문제