0

Consider the following code that uses and_then to chain together two methods returning outputs wrapped up as Results:

use std::net::TcpListener;

fn main() {
    match TcpListener::bind("127.0.0.1:2000").and_then(|s| s.accept()) {
        Ok((stream, addr)) => ...,
        Err(e) => ...,
    }
}

Is there a more elegant way to chain together bind and accept? This seems like a common pattern. I was hoping that maybe ? could help:

match TcpListener::bind("127.0.0.1:2000")?.accept()

But this won't compile:

error[E0277]: the trait bound `(): std::ops::Try` is not satisfied
  --> src/main.rs:21:11
   |
21 |     match TcpListener::bind(socket)?.accept() {
   |           --------------------------
   |           |
   |           the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
   |           in this macro invocation
   |
   = help: the trait `std::ops::Try` is not implemented for `()`
   = note: required by `std::ops::Try::from_error`

(I'm running rustc 1.20.0 (f3d6973f4 2017-08-27).)

EDIT: ? does not seem to have the semantics I have in mind, which also explains the error, see 1 (thanks, @Joe Clay). I am looking for the same behavior I get with and_then, but with a more elegant syntax.

smolkaj
  • 91
  • 4
  • The error message is very clear. – Boiethios Sep 04 '17 at 12:21
  • But `bind` *does* return `Result`, see https://doc.rust-lang.org/std/net/struct.TcpListener.html – smolkaj Sep 04 '17 at 12:35
  • 1
    Yes, but *`main` itself* doesn't. Using `?` is functionally equivalent to adding a match statement that, in the `Err` case, makes the enclosing function return the error - therefore, using it inside a function that isn't marked as returning `Result` is a type error. – Joe Clay Sep 04 '17 at 12:44
  • 1
    Until the relevant RFC gets implemented, the solution I've tended to use is the one displayed in [this answer](https://stackoverflow.com/a/30556164/5436257) - all `main` does is handle the printing of the successful result/error, delegating to another function that returns `Result` for the actual logic. – Joe Clay Sep 04 '17 at 12:47
  • 2
    @smolkaj *in* =/= *on*; but maybe they should have written: ``the `?` operator can only be used inside a function that returns `Result` `` – Boiethios Sep 04 '17 at 13:10

0 Answers0