Are nested matches a bad practice in idiomatic Rust?
Result
and Option
have some great methods for making code like that simpler.
fn get_url_content(url: &str) -> Option<String> {
let client = Client::new();
let res = client.get(url)
.send()
.ok() // Convert to Option, discarding error
.and_then(|mut res| {
let mut s = String::new();
let result = res.read_to_string(&mut s);
result.ok().map(|_| s)
}
})
}
I recommend looking through the documentation for Result and Option; there are methods for most combinations of conversions between them, and acting on either the success or error half.
If you can change get_url_content
to return a Result
, I would recommend that (see the error handling documentation. With your own error type and some implementations of From
, the function then becomes (
fn get_url_content(url: &str) -> Result<String, MyError> {
let client = Client::new();
let mut s = String::new();
let got = try!(client.get(url));
let sent = try!(got.send());
try!(sent.read_to_string(s));
Ok(s)
}
And probably even simpler with the new ?
operator.
The easiest way to make things a bit cleaner is to drop some braces:
match client.get(url).send() {
Ok(mut res) =>
match res.read_to_string(&mut s) {
Ok(_) => Some(s),
Err(_) => None,
},
Err(_) => None,
}
The inner match can be expressed a little cleaner perhaps as
match client.get(url).send() {
Ok(mut res) =>
res.read_to_string(&mut s).ok().map(|_| s),
Err(_) => None,
}
This suggests using a map
on the outer type (to get Result<Option<_>, _>
) and then dropping the result with .unwrap_or(None)
or .unwrap_or_default()
client.get(url).send()
.map(|mut res| res.read_to_string(&mut s).ok().map(|_| s))
.unwrap_or(None)