Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are nested matches a bad practice in idiomatic Rust?

Tags:

I have a get_url_content function and don't care about errors (it's just a test). It returns an 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 I find it's not easy to read. I think there are some best practices about this kind of case to make it more readable. Are nested matches a bad practice (like callback hell in JS) and if so, how to avoid it?

like image 941
rap-2-h Avatar asked Jul 22 '16 09:07

rap-2-h


1 Answers

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)
like image 198
Veedrac Avatar answered Sep 29 '22 07:09

Veedrac