🤛
Rustでエラーを握りつぶす
エラーは握りつぶすのは良くないと思う(小学生並みの思考)ので、こんなもん個人用途で書き捨てる時にしか使わないと思いますよ。
書き捨てる時に、失敗するかもしれないけどunwrap()
だと強制終了してくるから困る!!からその対処
?
演算子を使う
ResultかOptionを返す関数には?
演算子が使えます。?
演算子の対象がSome
だったりOk
だったりした場合は中身を取り出してくれて、Err
だったりNone
だったりした場合は早期リターンしてくれるものですね。エラー処理がだるい場合はこいつを使っておけば問題ありませんね
fn returns_result() -> Result<u32, Box<dyn std::error::Error>> {
let mut string = String::new();
std::io::stdin().read_line(&mut string)?;
let number = string.parse::<u32>()?;
Ok(number)
}
fn returns_option() -> Option<u32> {
let mut v = vec![1, 2, 3, 4, 5].into_iter();
let first = v.next()?;
let second = v.next()?;
let third = v.next();
third
}
Optionを使う
Result
型を返してくる関数も.ok()
を使って全部Option
にします。これでエラー情報が皆無になりますね!(^v^)/
fn aiueo() -> Option<()> {
let mut v = vec![1, 2, 3, 4, 5].into_iter();
// `Option`を返すので単に`?`を付けるだけでいい
let first = v.next()?;
let second = v.next()?;
let mut string = String::new();
// `Result`型を返してくるので`.ok()`で`Option`型に変えて`?`
std::io::stdin().read_line(&mut string).ok()?;
let number = string.parse::<u32>().ok()?;
Some(())
}
失敗するかもしれないイテレータ処理には.collect::<Option<V>>()
が使えるので活用しましょう
(下のはHTTPのリクエストヘッダーをHashMap
に変換する例(※書き捨て))
fn parse_headers(request_headers: Vec<String>) -> Option<HashMap<String, String>> {
request_headers
.into_iter()
.map(|header| {
let mut pair = header.split(": ").map(|x| x.to_string());
match (pair.next(), pair.next()) {
(Some(key), Some(value)) => Some((key, value)),
_ => None,
}
})
.collect::<Option<HashMap<String, String>>>()
}
で、こうみんながみんなOptionを返して伝播していって、最終的にmainくらいの上層で握りつぶします。match
でもunwrap_or_else
でもなんでも好きなように
エラーがあったらエラーがあったことくらいは情報として出してもいいかもですね
match aiueo() {
None => eprintln!("エラー有り"),
Some(_) => (),
};
Resultを使う
握りつぶしてるせいでどこでエラーが起きたかも分からねえじゃねえか!って思うのであればOptionを.ok_or()
でResult
に変換するのもありでしょう
「どこでエラーが起きたか」くらいの気持ち程度のエラー情報で
fn aiueo_result() -> Result<(), Box<dyn std::error::Error>> {
let mut v = vec![1, 2, 3, 4, 5].into_iter();
// `.ok_or()`でResultに変える
let first = v.next().ok_or("vの1個目が無い")?;
let second = v.next().ok_or("vの2個目がない")?;
let mut string = String::new();
std::io::stdin().read_line(&mut string)?;
let number = string.parse::<u32>()?;
Ok(())
}
fn main() {
match aiueo_result() {
Err(e) => println!("エラー有り:{}", e),
Ok(()) => (),
}
}
まとめ
マジで書き捨て用途以外に使わないと思う
Discussion