Are nested matches bad practice in idiomatic rust?

I have a function get_url_contentand don't care about errors (this is just a test). He returns Option<String>.

extern crate hyper;

use std::io::Read;
use hyper::client::Client;

fn get_url_content(url: &str) -> Option<String> {
    let client = Client::new();
    let mut s = String::new();

    match client.get(url).send() {
        Ok(mut res) => {
            match res.read_to_string(&mut s) {
                Ok(_) => {
                    Some(s)
                },
                Err(_) => {
                    None
                }
            }
        },
        Err(_) => {
            None
        }
    }
}

This function works fine, but it’s not easy for me to read it. I think there are some best practices in this case to make it more readable. Are nested matches a bad practice (e.g. callback hell in JS), and if so, how to avoid this?

+7
source share
2 answers

The easiest way to make things a little cleaner is to drop a few brackets:

match client.get(url).send() {
    Ok(mut res) =>
        match res.read_to_string(&mut s) {
            Ok(_) => Some(s),
            Err(_) => None,
        },
    Err(_) => None,
}

Inner coincidence 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,
}

map ( Result<Option<_>, _>), .unwrap_or(None) .unwrap_or_default()

client.get(url).send()
      .map(|mut res| res.read_to_string(&mut s).ok().map(|_| s))
      .unwrap_or(None)
+8

Result Option .

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)
                     }
           })
}

Result Option; , .

get_url_content, Result, (. . From, (

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)
}

, , ?.

+4
source

Source: https://habr.com/ru/post/1648758/


All Articles