Fehler beim Umgang mit Best Practices

8

Ich habe Rusts Dokumentation durchforstet und versucht, ein einfaches esoterisches Beispiel für meinen eigenen Bildungsnutzen auszuführen, mehr als nur praktisch. Während ich das tue, kann ich nicht den Kopf darüber verschließen, wie Rusts Fehlerbehandlung verwendet werden soll.

Das Programmierbeispiel, das ich verwende, ist eine Funktion zu schreiben, die einen Befehl in einer Shell ausführt. Aus dem Ergebnis des Befehls möchte ich stdout (als String oder &str ) abrufen und wissen, ob der Befehl fehlgeschlagen ist oder nicht.

Die std::process::Command Struktur gibt mir die Methoden, die ich will, aber es scheint dass der einzige Weg sie zu kombinieren kludgy und peinlich ist:

%Vor%

Insbesondere scheinen die verschachtelten Match-Blöcke innerhalb von run_cmd wirklich peinlich zu sein, und die verschachtelten Match-Blöcke in main sind sogar noch schlimmer.

Was ich wirklich gerne machen würde, wäre eine allgemeinere Fehlerklasse als FromUtf8Error oder io::Error , die ich einfach in einen konkreten Typ umwandeln kann, aber es erscheint nicht der Typ System wurde auf diese Weise entworfen, also musste ich das rohe CmdError eher als einen Unionstyp verwenden / p>

Ich bin mir sicher, dass es einen einfacheren Weg gibt, dies zu tun, der idiomatischer ist, aber ich habe es nicht aus der Dokumentation gefunden, die ich bisher gelesen habe.

Alle Zeiger werden geschätzt.

    
zjagannatha 07.03.2015, 05:46
quelle

1 Antwort

12

Dinge wie diese zu definieren, ist derzeit keine besonders nette Sache; Es gibt ein paar Dinge, die Sie mit Ihrem benutzerdefinierten Fehlertyp einrichten müssen, aber nachdem Sie das erledigt haben, sind die Dinge viel einfacher.

Zuerst möchten Sie std::error::Error für CmdError implementieren (was std::fmt::Display und std::fmt::Debug erfordert), und dann, damit try! automatisch arbeiten kann, std::convert::From<std::string::FromUtf8Error> und std::convert::From<std::io::Error> . Hier sind die Implementierungen von denen:

%Vor%

(Die description -Methode in der Error -Implementierung könnte möglicherweise einen String zurückgeben, der nicht auf dem umgebrochenen Fehler basiert, zB "Befehl fehlgeschlagen". Wenn man die Details möchte, sind sie immer noch in Error.cause() .)

Nach der Implementierung dieses Loses sind die Dinge viel einfacher, weil wir try! . run_cmd kann so geschrieben werden:

%Vor%

Da try! die From -Infrastruktur verwendet, ist dies alles viel einfacher; Die erste Zeile gibt möglicherweise Err(CmdError::IoError(_)) zurück (für Command.output() gibt Result<_, io::Error> zurück) und die zweite Zeile gibt möglicherweise Err(CmdError::UtfError(_)) zurück (für String::from_utf8(…) gibt Result<_, FromUtf8Error> zurück).

Ihr main kann auch etwas einfacher sein, wenn der Zweig err keinen weiteren Abgleich benötigt, wenn Sie sich nicht für den speziellen Fehler interessieren; Da es jetzt fmt::Display implementiert, können Sie es einfach direkt verwenden.

Übrigens sollte {:} in einer Formatzeichenfolge als {} geschrieben werden; Das : ist überflüssig, wenn nichts folgt. ( {:?} würde funktionieren, wenn Debug output angezeigt wird. Sie sollten jedoch Display verwenden, wenn es auf den Benutzer ausgerichtet ist.)

    
Chris Morgan 07.03.2015 06:34
quelle

Tags und Links