Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upResult::pass(), turning Result<T,E> into Result<U,F>, if From is set up #1996
Conversation
This comment has been minimized.
This comment has been minimized.
|
FWIW, here's a stab at how the example might look like using fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
for stream in listener.incoming() {
let res: Result<(), ServerError> =
do catch {
handle(&mut stream?)
};
if let Err(e) = res {
println!("Error occured: {:?}", e);
}
}
}
fn handle(stream: &mut TcpStream) -> Result<(), ServerError> {
Ok(write!(stream, "hello!")?)
}Or somewhat weird-looking but both shorter and stable: let res = (|| handle(&mut stream?))();Compilable: https://play.rust-lang.org/?gist=6877f6d66d7e1255797b8386c61ca96b&version=nightly&backtrace=1 (I don't have an opinion on the API right now, but since it's proposed to do a similar error conversion as |
BurntSushi
added
the
T-libs
label
May 9, 2017
This comment has been minimized.
This comment has been minimized.
Ok(write!(stream, "hello!")?)This is definitely convoluted and hard to explain. There, I would prefer: write!(stream, "hello!").map_err(ServerError::from)The
I will extend the motivating example by adding more result cases in Code added for completeness sake: #![feature(catch_expr)]
use std::net::{TcpListener, TcpStream};
use std::io::Write;
#[derive(Debug)]
enum ServerError {
IoError(std::io::Error),
// some more cases
}
impl From<std::io::Error> for ServerError {
fn from(e: std::io::Error) -> ServerError {
ServerError::IoError(e)
}
}
trait ResultExt<T, E> {
fn pass<X, Y>(self) -> Result<X, Y> where T: Into<X>, E: Into<Y>;
}
impl<T,E> ResultExt<T, E> for Result<T, E> {
fn pass<X, Y>(self) -> Result<X, Y> where T: Into<X>, E: Into<Y> {
self.map(T::into).map_err(E::into)
}
}
fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
for stream in listener.incoming() {
let res = stream.pass()
.and_then(|mut stream| handle(&mut stream) );
if let Err(e) = res {
println!("Error occured: {:?}", e);
}
}
}
fn handle(stream: &mut TcpStream) -> Result<(), ServerError> {
write!(stream, "hello!").pass()
} |
This comment has been minimized.
This comment has been minimized.
|
Interesting RFC! I think this would be a great conversion to have. It sounds like it would make it really easy to write code like this: fn bar() -> Result<X, Y> {
foo().pass()
}Here's my question: If The RFC mentions that "This is more general, but possibly harder to discover, as the appropriate method to call would end up Except that's the whole point of having a general conversation trait. If someone knows that they can call We should be encouraging people to understand and use I think it would be better to avoid adding another method for people to remember and use into instead. If you're worried about discoverablity, we can add something to the module level docs. I don't think it's worth it to add another method here just for this. I really like your idea of implementing that conversation. I just don't agree that adding another method called pass is a good way to implement it when we've already got an established trait for conversions. |
This comment has been minimized.
This comment has been minimized.
|
@sunjay I suspect most folks would prefer it working with |
This comment has been minimized.
This comment has been minimized.
|
Thanks @BurntSushi! @skade It may be worth adding something more to the RFC about why Into isn't possible. |
This comment has been minimized.
This comment has been minimized.
My initial argument was that, you will have an already big API surface of result around handling Err and Ok (and_then, and, or, or_else...), but The argument about collisions from the RFC thread seems more striking to me, though. I'll add it later. |
aturon
self-assigned this
May 9, 2017
This comment has been minimized.
This comment has been minimized.
|
I want to make a sort of philosophical comment about using Someday it will work (because we want intersection impl specialization as soon as its feasible to implement it), and the impl should exist so that you can use it generically. However, I think there are many cases where creating an alias for a trait method that's an inherent method with a type specific name is just a good idea. An example of this that comes immediately to mind is the Its great that you can abstract over these fundamentally similar operations (cough cough monoid), but for a newer user who just wants to merge two hash maps together, I'm not sure |
This comment has been minimized.
This comment has been minimized.
|
I updated the RFC with the feedback from Twitter, here and IRLO. Also, I found that impl<T, E, U: From<T>, F: From<E>> From<Result<T, E>> for Result<U,F> {
fn from(self) -> Result<U,E> {
self.map(U::from).map_err(F::from)
}
}The reason is that - currently - I also added "coalesce" as a name suggestion to the bikeshed. |
This comment has been minimized.
This comment has been minimized.
|
OTOH, if you know that |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 The name is a stand-in, feel free to bikeshed. I don't agree that people will use the more general name at any time, though, see the whole behaviour around (String::from, into and friends). They mostly follow a convention. But, as written above, From isn't possible, currently, anyways. |
This comment has been minimized.
This comment has been minimized.
|
I'm really struggling with the name. As a non-native speaker, I'm a bit at loss there :). |
This comment has been minimized.
This comment has been minimized.
burdges
commented
May 11, 2017
|
I suppose |
This comment has been minimized.
This comment has been minimized.
|
I think we’d also benefit from a |
This comment has been minimized.
This comment has been minimized.
alilleybrinker
commented
May 12, 2017
|
So I don't think there's an existing name for anything like this in Haskell. I agree that |
This comment has been minimized.
This comment has been minimized.
|
Yes, |
This comment has been minimized.
This comment has been minimized.
|
@phaazon I'm not sure if I agree with the need for a bimap method here. res.map_err(function_one).map(function_two)is fine, IMHO, unless the goal is chaining results together like the proposed method does. I just don't think passing functions in Rust is as ergonomic as in Haskell and that shows here. @AndrewBrinker I always avoid very generic names like |
This comment has been minimized.
This comment has been minimized.
jan-hudec
commented
May 14, 2017
I disagree. When there is just one name, everybody will learn that one name, so everybody will know what it means when they read each others code. When there are type-specific aliases, especially aliases that are different for different types, most won't remember all of them and will have to look them up all the time. And remember, code is written once, but read many times.
That would be one language I don't want to have anything to do with, because that would be just mess. Fortunately the one I usually use has
Yet, it is important that they discover This should be solved by improving the documentation, not adding methods. |
This comment has been minimized.
This comment has been minimized.
|
Nitpick - don't forget to fill in the start date with 2017-05-09 |
This comment has been minimized.
This comment has been minimized.
weargoggles
commented
Aug 18, 2017
|
I'm having trouble tracking down the rationale for From's reflexive implementation. Can anyone point me at the conversion RFC? If that reflexive implementation could be removed, specialisation would not be necessary. |
This comment has been minimized.
This comment has been minimized.
weargoggles
commented
Aug 18, 2017
•
|
Apologies. I've found the conversion traits RFC. It doesn't specify that there should be reflexive implementation of the trait, does anyone know if it's required elsewhere? |
This comment has been minimized.
This comment has been minimized.
|
@weargoggles It's hinted at under the name of Non-reflexive fn open<P: Into<Path>>(&P) -> Result<File, Error> {
}It would be awkward if that function couldn't be called with a Also, in the context of this RFC, it means that you shouldn't call |
This comment has been minimized.
This comment has been minimized.
weargoggles
commented
Aug 18, 2017
|
@skade Oh! I understand. Thanks for clearing that up. |
This comment has been minimized.
This comment has been minimized.
|
@weargoggles |
This comment has been minimized.
This comment has been minimized.
|
The libs team discussed this RFC in our meeting today (sorry for the very long delay!). The general feeling was that:
|
This comment has been minimized.
This comment has been minimized.
|
I'd love to see this method added, I think it is useful. But imo.. the names We could say: Another idea is Tho... After writing and reaching this point I've started to think that a more general name is a good thing because it is a very general operation. With that rationale, I think the best name that isn't |
This comment has been minimized.
This comment has been minimized.
burdges
commented
Jan 26, 2018
|
I feel the word Right now, this reads |
This comment has been minimized.
This comment has been minimized.
|
@burdges I'd strike I'm not sure I get why mapping is wrong here tho if in the past tense - something has been (bi-)mapped, with |
This comment has been minimized.
This comment has been minimized.
|
This has been here for quite some time now and I'm not personally sold that the convenience here is worth it, so I'd like to propose that we close this RFC: @rfcbot fcp close |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Apr 19, 2018
•
|
Team member @alexcrichton has proposed to close this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
rfcbot
added
the
proposed-final-comment-period
label
Apr 19, 2018
rfcbot
added
the
final-comment-period
label
May 2, 2018
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
May 2, 2018
|
|
rfcbot
removed
the
proposed-final-comment-period
label
May 2, 2018
This comment has been minimized.
This comment has been minimized.
golddranks
commented
May 8, 2018
•
|
I felt the need for this just today, while wrapping two things with similar interfaces into an enum. The things have similar but not the same return values: I also agree with @withoutboats that a separate method for doing the conversion wouldn't be too bad! I'm sad to see this proposal moving towards closing, especially that @withoutboats and @aturon who seemed to be positive towards this proposal haven't checked their boxes. At least I hope that we will revisit this when specialization allows |
rfcbot
added
the
finished-final-comment-period
label
May 12, 2018
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
May 12, 2018
|
The final comment period, with a disposition to close, as per the review above, is now complete. By the power vested in me by Rust, I hereby close this RFC. |
skade commentedMay 9, 2017
•
edited
IRLO discussion here.
Rendered
I would be willing to implement this or mentor an implementation.