Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended Try RFC #211

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions active/0000-extended-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
- Start Date: 2014-06-25
- RFC PR:
- Rust Issue:

# Summary

Extend the `try!` macro to include an optional second parameter that is a constructor to wrap
around the original error in case of failure.

# Motivation

`try!` is a useful macro when dealing with many functions that return `Result`s, but they become
useless when the `Result` type that the programmer wants to return has a different failure type.
For example, in a function that uses Io and Regex, two different error types could be generated
(IoError, and Regex::Error). The author could not choose either of these errors to return because
neither is extendable with the other. Instead it is common for library and application authors
to create their own error types that wrap the errors that could possibly be produced. Unfortunately,
this means that the `try!` macro is no longer useful.

# Detailed design

This RFC proposes adding another argument to the `try!` macro that would be used as a constructor
to wrap around existing error types. For example:

```rust
enum MyError {
IoFailed(IoError),
RegexFailed(regex::Error)
}

fn read_then_regex(filename: &str, regex: &str) -> MyError {
let file = try!(File::open(filename), IoFailed);
let regex = try!(Regex::new(regex), RegexFailed);
// do things
}

```

The desugared version of this example (which is required to implement this pattern today)
would look like:

```rust
fn read_then_regex(filename: &str, regex: &str) -> MyError {
let file = match File::open(filename) {
Ok(a) => a,
Err(x) => IoFailed(x)
};
let regex = match Regex::new(regex) {
Ok(a) => a,
Err(x) => RegexFailed(x)
};
// do things
}
```

The motivation for this improvement is the exact same as the motivation for the original `try!`
macro.

The original form of the `try!` macro would still be valid and would continue to work without
any changes.

# Drawbacks

Adds confusion. It is not immediately obvious as to what the 2nd argument is for if
the reader is not already familiar with it.

# Alternatives

* Create another macro that is very similar
* (named `try_or!` ?).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the try! macros is widely used and mostly liked, creating a new macro seems like it would be a much better idea. In that case, I would recommend implementing it as an external library and getting some use and experience, then submitting a PR to add it to std (I don't think that would require an RFC), and perhaps finally an RFC to add it to the prelude if it is very popular.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nick29581 The existing try!() can easily be extended to take two arguments without breaking any backwards compatibility. The suggestion for a new macro is only as a potential readability aid. Personally, I think using a new macro is unnecessary, providing a second arg to try!() should be visible enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its also a good way to get some experience using this without affecting a really crucial macro. I mean that if we added this, decided it was a mistake, then took it out again, it could be painful. So there is a high bar for acceptance. If we had some use of this beforehand to convince us it was a good idea, then it would be easier to accept.

So, change the last sentence in my previous comment to "submit an RFC to merge the new macro in with Try!"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted this macro bad enough that I made my own cargo project that implements this RFC.
https://github.com/TyOverby/try_or

I'm pretty bad at writing macros, so I wouldn't suggest that this be made the official implementation, but I've found that it is incredibly handy.

* Create another macro that is very similar and place it in an external library