Why use try! with write! for fmt::Display of struct?


#1

[total newbie] reading the example [ http://rustbyexample.com/hello/print/print_display/testcase_list.htmlhttp://rustbyexample.com/hello/print/print_display/testcase_list.html]( http://rustbyexample.com/hello/print/print_display/testcase_list.htmlhttp://rustbyexample.com/hello/print/print_display/testcase_list.html), I don’t understand why I need to wrap write! in try!. How does this handle dealing with all the Result values from individual elements of the vec? A fragment:

 impl fmt::Display for List {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let List(ref vec) = *self;
         try!(write!(f, "["));
         for (count, v) in vec.iter().enumerate() {
             if count != 0 { try!(write!(f, ", ")); }
             try!(write!(f, "{}", v));
         }
         write!(f, "]")
     }
 }

#2

try!(...) is a macro that expands to something like:

match ... {
    Ok(v) => v,
    Err(e) => return Err(e),
}

(This is a simplified version but conceptually correct.)

So your code above actually looks like:

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let List(ref vec) = *self;
        match write!(f, "[") {
            Ok(_) => {},
            Err(e) => return Err(e), // handle the error by returning early
        }
        for (count, v) in vec.iter().enumerate() {
            if count != 0 {
                match write!(f, ", ") {
                    Ok(_) => {},
                    Err(e) => return Err(e), // handle the error by returning early
                }
            }
            match write!(f, "{}", v) {
                Ok(_) => {},
                Err(e) => return Err(e), // handle the error by returning early
            }
        }
        write!(f, "]")
    }
}

This makes the error handling more visible, but try!(...) is really doing the same thing.