2016-07-22 4 views
4

私はget_url_contentの機能を持っており、エラーについては気にしません(これは単なるテストです)。 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 
     } 
    } 
} 

この機能はうまくいきますが、読みにくいことがわかりました。この種のケースについて、より読みやすくするためのベストプラクティスがあると思います。ネストされたマッチはJSのコールバック地獄のような悪い習慣であるかどうか、もしあればそれを避ける方法はありますか?

答えて

5

最も簡単な方法は、いくつかの括弧をドロップすることです:

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

内側一致これは「(Result<Option<_>, _>を取得するために)、外側種類mapを使用した後のdoesn .unwrap_or(None)

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

と結果をドロップ示唆

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

として恐らく少しクリーナーを表すことができます。 '.map(| mut res | 's'が変更可能に借用され、同じ式で返されるため、res.read_to_string(&muts).ok()。map(| _ | s))'が失敗します。 –

+0

それは動作します。 Thxはこのステップのステップ回答で、より良いRustを理解するのに役立ちます。 –

+0

@ChrisEmersonいいえ。出力の有効期間は借用に依存しないためです。 – Veedrac

4

ResultOptionには、このようなコードを簡単にするためのいくつかの素晴らしい方法があります。

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

私はResultOptionのドキュメントを通して見てお勧めします。それらの間の変換の大部分の組み合わせのためのメソッドがあり、成功またはエラーの半分に作用します。

は、独自のエラータイプと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) 
} 

そして、とさらに簡単になりますがResultを返すようにget_url_contentを変更することができる場合、私は(the error handling documentationを参照することをお勧めします。 。物事が少しきれいにする新しい?オペレータ

関連する問題