2016-08-09 5 views
2

Ich versuche, eine Reihe von Json Objekte mit potenziellen Fehlern zu analysieren, die die gesamte Funktion abbrechen.Schöne Möglichkeit, mit potenziellen Fehler zu mappen

Idealerweise würde ich so etwas wie:

fn .... -> Result<Vec<Video>, YoutubeParseError> { 
    ... 
    let videos = try!(doc.find("items"). 
     and_then(Json::as_array). 
     ok_or(YoutubeParseError)); 

    Ok(videos.into_iter(). 
     map(|item| try!(json_to_video(item))). 
     collect()) 
} 

Aber natürlich nicht versuchen, die map() auf Fehler entkommt und statt Result<Vec<Video>,_>, bekomme ich Vec<Result<Video,_>>. Ich könnte dies als manuelle Iteration umschreiben, indem ich Elemente in ein neues Vec einfüge, aber ich habe das Gefühl, dass mir eine einfachere Art des Umgangs damit fehlt.

Gibt es eine bestehende Funktion, die mich leicht von Iter<Result<T>> zu Result<Vec<T>,_> bringen würde?

+0

Ich glaube nicht, dass zweiter Versuch! funktioniert wie du willst. Versuchen! wird dich aus der Schließung bringen. By the way haben Sie sich 'flat_map' angeschaut – sgldiv

Antwort

0

In funktionalen Programmiersprachen können Sie Optionen und Ergebnisse als Container behandeln und Rust ist ähnlich, so können Sie map/flat_map über sie. Sie könnten dies mit flat_map tun. Wenn videos bereits ein Vektor ist, können Sie einfach die erwartete Anzahl von Ok gegen eine flat_map PED-Länge testen, um zu entscheiden, ob Sie Ok zurückgeben.

Sie sollten jedoch versuchen, die Dinge träge zu halten und nach dem ersten Fehler nicht weiter zu analysieren. take_while wäre hier eine Option. In jedem Fall müssen Sie verfolgen, ob Sie auf dem Weg eine parse_failure gesehen haben. Etwas wie unten funktioniert - es zeigt, wie flat_map Tropfen Error s, aber es analysiert mehr als nötig. Sie könnte auch ein .filter und dann .map verwenden, um das Parse-Ergebnis

fn get_videos(test: &Vec<&str>) -> Result<Vec<u32>, &'static str> { 
    let videos = ... 
    let expected = videos.len(); 
    let extracted = v.into_iter().flat_map(|x| json_to_video(x)).collect(); 
    if extracted.len() == expected { 
     Ok(extracted) 
    } else { 
     Err("__CANNOT_PARSE__") 
    } 
} 

Hier ist eine Option zu bekommen, um es gemächlich zu tun -

let extracted = videos.map(|x|json_to_video(x)) 
         .take_while(|x|x.is_ok()) 
         .map(|x|x.ok().unwrap()) 
         .collect() 

Sie unwrap nennen können, wie Sie alles ab ersten Ausfall gesunken. Jetzt zurück Ok wenn extracted.len() == videos.len()

+0

@shepmaster ... wie geschrieben es über den ersten Fehler analysiert. – sgldiv

+0

Ah, das ist ein guter Punkt! Ich werde meinen Kommentar löschen, um Verwirrung zu vermeiden. – Shepmaster

Verwandte Themen