4 ms·
Python's with has no advantages at all over destructors that I'm aware of (it does have some disadvantages, since it's easy to forget) and I'm curious to ask wh
by Jweb_Guru 12y ago
Python's with has no advantages at all over destructors that I'm aware of (it does have some disadvantages, since it's easy to forget) and I'm curious to ask what you think they are. This may help those of us who are extremely happy with Rust's error handling story better understand your complaints. You keep talking about "excessive boilerplate" and the like, but that simply isn't what I observe in practice--it could certainly be better, but existing solutions are fairly unobtrusive. You also claim that exceptions are "successful" in Python, but I have had just as many issues with exceptions in Python as I have in Java (if not more, because the exceptions are not part of the function signature).
The problems with exceptions are well-documented (they require the programmer to write all his or her code transactionally, leading to so-called exception safety issues). Subclassing doesn't address the major issues of error handling at all, as far as I know, but again--I'd be interested to hear how you feel they are different (Rust already has an IOError that suffices for the cases you seem to be concerned about, but in practice there are many more types of error than that).
- Animats 12y agoHacker News isn't really a good place to post code, but here's an excerpt of the boilerplate required in Rust code that reads XML to pass I/O, HTTP, and XML parsing errors upward. This, according to the reference above on the new style of error handling, is now the official right way to do it.[1] Works fine. You get to repeat all this each time you define a new result type with possible lower level errors. What's wrong with this picture? // // Return type and its error handling // pub type FeedResult<T> = Result<T, FeedError>; /// A set of errors that can occur handling RSS or Atom feeds. #[derive(Debug, PartialEq, Clone)] // crank out default functions pub enum FeedError { /// Error detected at the I/O level FeedIoError(IoError), /// Error detected at the HTTP level FeedHTTPError(hyper::HttpError), /// Error detected at the XML parsing level FeedXMLParseError(xml::BuilderError), /// XML, but feed type not recognized, FeedUnknownFeedTypeError, /// Required feed field missing or invalid FeedFieldError(String), /// Got an HTML page instead of an XML page FeedWasHTMLError(String) } // // Encapsulate errors from each of the lower level error types // impl error::FromError<hyper::HttpError> for FeedError { fn from_error(err: hyper::HttpError) -> FeedError { FeedError::FeedHTTPError(err) } } impl error::FromError<old_io::IoError> for FeedError { fn from_error(err: IoError) -> FeedError { FeedError::FeedIoError(err) } } impl error::FromError<xml::BuilderError> for FeedError { fn from_error(err: xml::BuilderError) -> FeedError { FeedError::FeedXMLParseError(err) } } impl fmt::Display for FeedError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { &FeedError::FeedIoError(ref xerr) => xerr.fmt(f), // I/O error &FeedError::FeedHTTPError(ref xerr) => xerr.fmt(f), // HTTP error &FeedError::FeedXMLParseError(ref xerr) => xerr.fmt(f), // XML parse error &FeedError::FeedUnknownFeedTypeError => write!(f, "Unknown feed type."), &FeedError::FeedFieldError(ref s) => write!(f, "Required field \"{}\" missing from RSS/Atom feed.", s), &FeedError::FeedWasHTMLError(ref s) => write!(f, "Expected an RSS/ATOM feed but received a web page \"{}\".", s) //_(ref xerr) => xerr.fmt(f) // would be convenient, but not allowed in Rust. } } } [1] http://lucumr.pocoo.org/2014/11/6/error-handling-in-rust/ http://lucumr.pocoo.org/2014/11/6/error-handling-in-rust/
- Jweb_Guru 12y agoYou don't have to do any of this. You can just use Box<Error> in your Result and handle all types that implement FromError, if you so choose. You can also decide to do it this way, if you want to have more explicit error messages. Or you can simply forgo all this and return errors explicitly. I'm frankly not sure why you think this is boilerplate, though: what, indeed, is wrong with this picture? Maybe I'm simply missing the obvious, but this doesn't even seem like that much code to me, especially given that each of your error types would have to be classes in other languages. (BTW, you don't need to prefix all the errors with Feed because they are already namespaced). Once you've written the above, you can simply try! everywhere and get automatic conversions--and you use try! a lot more often than you define new result types. Your example also looks very much like what I would write in a language like Java, where exceptions are actually part of the signature (which is the approach Rust takes). Perhaps you are talking to the wrong person here, but I have never had an issue with Java's approach to checked exceptions, only the many ways the language provides to undermine them and the difficulty of creating new error types without ADTs. In any case, you still haven't addressed my remaining questions re: exceptions. We may disagree on whether the above is boilerplate, but given that exceptions have other problems they are still not a drop-in replacement. I think if you consider boilerplate to be the biggest issue in error handling, you and I likely fundamentally disagree.