SlideShare a Scribd company logo
Mobility Technologies Co., Ltd.
Rust Error Handling
2021/04/28 @MoT.rs
Shunsuke Nakamura
AI技術開発部
Mobility Technologies Co., Ltd.
今日やること
2
- Rustのエラー表現

- エラーによるフロー制御

- よくあるエラー処理

- エラー時の早期リターン

- ライブラリを使用したエラー処理のベストプラクティス

Mobility Technologies Co., Ltd.
Rustのエラー表現
3
■ Rust には Java や Python のような例外はなく、Result型でエラーを表現する
■ Result型は Result<{Ok の時の中身の型}, {Errの時の中身の型}> で定義する
■ 実体はただのEnum型
Mobility Technologies Co., Ltd.
問題1
4
Rust playground にかかれているコードのコンパイルエラーを解消してください
Mobility Technologies Co., Ltd.
解説1
5
Okの際には i32 を、Err の際には ZeroDivisionError を返しているため、
ここでは Result<i32, ZeroDivisionError> を返せば良い
Mobility Technologies Co., Ltd.
エラーによるフロー制御
6
Result型に対して、OkとErrで処理を分けたい場合
Result型はenumなので簡単なパターンマッチングで処理を分岐させられる
※ enumのVariantによるフロー制御
Mobility Technologies Co., Ltd.
問題2
7
Rust playground にかかれているコードのコンパイルエラーを解消してください
ヒント
1. Result<T, E>はOk<T>とErr<E>のenum型です
2. enum & パターンマッチによるフロー制御はスライドの前ページを参照してください
Mobility Technologies Co., Ltd.
解説2
8
Okの際は改めて中身を val として受けて表示し、
Errのときは _ で受けてエラーメッセージを出しています(eprintln! 等を使うとなお良い)
_ で受けると「この変数は使用しない」ということを意味します 参考
Mobility Technologies Co., Ltd.
よくあるエラー処理
9
■ 毎回パターンマッチを書くのは面倒。よくある処理はより短いメソッドを用意してくれている
■ unwrap: Okなら中身の値を取り出し、Errなら終了する。頻出
■ 問題点として、Errだと本当にpanic終了してしまうので、そこでコードが落ちる。
■ 本当に落として良いところでしか使ってはいけない
■ expect: Okなら中身の値を取り出し、Errならメッセージを付けて終了する
■ 問題点として、Errだと本当にpanic終了してしまうので、そこでコードが落ちる。
■ 本当に落として良いところでしか使ってはいけない
■ and_then: Okなら後段の処理を継続し、ErrならErrを伝播させていく
■ 例外処理を上段に任せて正常ケースだけ処理を進めていく時に便利
Mobility Technologies Co., Ltd.
問題3
10
Rust playground にかかれているコードのコンパイルエラーを解消してください
ヒント
Result型に用意されているメソッド一覧です
https://doc.rust-lang.org/std/result/enum.Result.html
Mobility Technologies Co., Ltd.
解説3
11
答え
unwrap, expect, and_then をそれぞれで使います
and_thenの中では次に実行するfunctionを渡してあげる必要があるので、
closure形式で渡しています
Mobility Technologies Co., Ltd.
早期リターンと?演算子
12
メソッドの中で使用している値がOkなら値を取り出して、Errなら早期returnする、というコードをよく書くこと
がある
下のようにパターンマッチを書いてもいいが、毎回これを書くのは面倒なので、
syntax sugarとして、?演算子が用意されている
Mobility Technologies Co., Ltd.
問題4
13
Rust playground にかかれているコードのコンパイルエラーを解消してください
Mobility Technologies Co., Ltd.
解説4
14
? を使って Err 時に早期 returnさせます。
もちろん match を使って早期 return させてもいいですが、? のほうが短く済むし、見やすいです
Mobility Technologies Co., Ltd.
複数のErrorを扱う
15
文字列 a, b を受け取って、i32型としてパースした後に割り算を行う関数を書いたとする
これは以下のコンパイルエラーとなる。
Mobility Technologies Co., Ltd.
より正確な?演算子
16
?演算子は受け取ったErr<E1>と、returnすべきErr<E2>が異なる時(E1 != E2のとき)、
型通りにreturnできるよう、E1をE2に型変換しようとしてくれる(同じ時は同じ型に変換する)
RustでのA → Bへの変換は、Bに対してFrom<A> trait が実装されていれば
- let a: A = From::from(B);
- let a = A::from(B);
のように行うことができる
つまり、?演算子はより正確には↓となる
Mobility Technologies Co., Ltd.
複数のErrorを扱う
17
文字列 a, b を受け取って、i32型としてパースした後に割り算を行う関数を書いたとする
これは以下のコンパイルエラーとなる。
ParseIntError -> &str への変換が実装されていない!
Mobility Technologies Co., Ltd.
問題5
18
Rust playground From traitを実装してください
Mobility Technologies Co., Ltd.
解説5
19
答え
From traitの実装はこのドキュメントに詳しいです。
impl From<変換元> for 変換先 … という実装をしておくと、
変換先::from(変換元) ができるようになります
余談ですが、この実装をすると自動で Into<変換先> for 変換元 が実装されるので、
let a: 変換先 = 変換元.into() が実行できるようになります
Mobility Technologies Co., Ltd.
問題6
20
Rust playground From traitを実装して早期returnしてください
Mobility Technologies Co., Ltd.
解説6
21
答え
先程と同様にFrom traitを実装します
これのおかげで、早期returnの?演算子がFrom::from変換を呼び出すことができます
Mobility Technologies Co., Ltd.
複数のErrorを扱う
22
一つの関数から複数のエラー(Err<E1>, Err<E2>, ...)が返る可能性がある、ということはよくある
対策としては、
- MyErrorのようなenumを定義し、全てのE1, E1→ MyError への変換(From)を実装する
- 自分で定義したエラー型に、毎回変換を実装ていくのは面倒
- Result<T, Box<dyn Error>> を返す関数である、と定義する
- Box<dyn Error> は Error traitを実装した任意の型、を意味する
- 自分で定義したエラー型に、毎回Error traitを実装していくのは面倒
→ 最近の主流: Error周りをよしなにやってくれる便利ライブラリを使う
- anyhow: アプリケーション用と言われている
- thiserror: ライブラリ用と言われている
Mobility Technologies Co., Ltd.
anyhow
23
アプリケーション用Errorライブラリ
- anyhow::Errorの提供
- Box<dyn Error> のようなものになっており、
std::error::Errorを実装しているものなら何でも渡せる
- Err(anyhow::anyhow!(“”)) だけで anyhow::Errorを生成してくれる
- anyhow::Resultを提供
- anyhow::Result<T> だけで Result<T, anyhow::Error> と同じ意味になる
- anyhow::Contextの提供
- 既存のErrorにメッセージを足すことができる
Mobility Technologies Co., Ltd.
thiserror
24
ライブラリ用Errorライブラリ
- thiserror::Errorの提供
- 独自で定義したstructやenumに対して
thiserror::Errorをderiveさせるだけで、
std::error::Errorを実装させることができる
- anyhowと組み合わせることで
かなりコード量を削ることができる
Mobility Technologies Co., Ltd.
問題7
25
Rust playground anyhow / thiserrorを使ってコードを修正してください
Mobility Technologies Co., Ltd.
解説8
26
まずは、std::error::Errorを実装した任意の型を返せるように変更する
途中経過1
しかしこれは残念ながらコンパイルエラーになる。理由は自分で定義したMyErrorがstd::error::Errorを実
装していないから(このstructはDebugしか実装していない)
自分でstd::error::Errorを実装するのは面倒なので、thiserrorを呼び出し、deriveさせるだけで実装したこ
とにしてしまう
途中経過2
最後に、Result<i32, Box<dyn std::error::Error>> がやや長ったらしいので、これを略記できる
anyhowを使って完成
答え
Mobility Technologies Co., Ltd.
参考ページ
27
■ Rust公式docs Error Handling
■ Rust by example Error Handling
■ Rustlings Error Handling
■ thiserror / anyhow の導入の流れ: Rust エラー処理2020

More Related Content

PDF
オブジェクト指向の設計と実装の学び方のコツ
PPTX
Dockerが抱えるネットワークの課題
PDF
オブジェクト指向プログラミングのためのモデリング入門
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
PDF
それはYAGNIか? それとも思考停止か?
PDF
ドメインオブジェクトの見つけ方・作り方・育て方
PDF
継承やめろマジやめろ。 なぜイケないのか 解説する
PPTX
テストコードの DRY と DAMP
オブジェクト指向の設計と実装の学び方のコツ
Dockerが抱えるネットワークの課題
オブジェクト指向プログラミングのためのモデリング入門
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
それはYAGNIか? それとも思考停止か?
ドメインオブジェクトの見つけ方・作り方・育て方
継承やめろマジやめろ。 なぜイケないのか 解説する
テストコードの DRY と DAMP

What's hot (20)

PDF
こわくない Git
PDF
リーンなコードを書こう:実践的なオブジェクト指向設計
PDF
できる!並列・並行プログラミング
PDF
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
PDF
Pythonによる黒魔術入門
PDF
SATySFi 最近の発展と目下実装中の変更
PDF
Sphinxでまとめる多言語環境APIドキュメント
PDF
オブジェクト指向できていますか?
PPT
ドメインロジックの実装方法とドメイン駆動設計
PDF
規格書で読むC++11のスレッド
PDF
日本語テストメソッドについて
PDF
ネットワーク ゲームにおけるTCPとUDPの使い分け
PPTX
プログラマがUnityでSTGを作った話
PDF
Redmine にいろいろ埋め込んでみた
PDF
serviceクラスをやめようサブクラスを使おう
PDF
いつやるの?Git入門
PDF
ノンプログラマでも今日から使える「Git」でバージョン管理
PDF
「日本語LaTeX」が多すぎる件について
PDF
続・PFN のオンプレML基盤の取り組み / オンプレML基盤 on Kubernetes 〜PFN、ヤフー〜 #2
PPTX
良いコードとは
こわくない Git
リーンなコードを書こう:実践的なオブジェクト指向設計
できる!並列・並行プログラミング
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
Pythonによる黒魔術入門
SATySFi 最近の発展と目下実装中の変更
Sphinxでまとめる多言語環境APIドキュメント
オブジェクト指向できていますか?
ドメインロジックの実装方法とドメイン駆動設計
規格書で読むC++11のスレッド
日本語テストメソッドについて
ネットワーク ゲームにおけるTCPとUDPの使い分け
プログラマがUnityでSTGを作った話
Redmine にいろいろ埋め込んでみた
serviceクラスをやめようサブクラスを使おう
いつやるの?Git入門
ノンプログラマでも今日から使える「Git」でバージョン管理
「日本語LaTeX」が多すぎる件について
続・PFN のオンプレML基盤の取り組み / オンプレML基盤 on Kubernetes 〜PFN、ヤフー〜 #2
良いコードとは
Ad

Similar to Rust Error Handling (20)

PDF
Python physicalcomputing
PDF
Kanazawa.js.Next
PDF
JJavaプログラム実行の仕組みと、高速・安定動作に向けた取り組み
PPTX
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
PDF
The Next Generation for C# Developers
PDF
JavaScript.Next
PDF
Unity2015_No10_~UGUI&Audio~
PPT
2008.10.18 L4u Tech Talk
PDF
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
PDF
JavaScript.Next Returns
PDF
はこだてIKA 第4回勉強会 単体テスト
PDF
第4回勉強会 単体テストのすすめ
PDF
nadoka さんの m17n 対応のベストプラクティス
PDF
Swift 2.0 で変わったところ「前編」 #cswift
ODP
Lt会01_uetch
PDF
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
PDF
Visual C++コード分析を支えるSAL
PDF
こんな辛いテストはいやだ
PDF
Inside FastEnum
PPT
Jpmobileを使ってみる
Python physicalcomputing
Kanazawa.js.Next
JJavaプログラム実行の仕組みと、高速・安定動作に向けた取り組み
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
The Next Generation for C# Developers
JavaScript.Next
Unity2015_No10_~UGUI&Audio~
2008.10.18 L4u Tech Talk
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
JavaScript.Next Returns
はこだてIKA 第4回勉強会 単体テスト
第4回勉強会 単体テストのすすめ
nadoka さんの m17n 対応のベストプラクティス
Swift 2.0 で変わったところ「前編」 #cswift
Lt会01_uetch
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
Visual C++コード分析を支えるSAL
こんな辛いテストはいやだ
Inside FastEnum
Jpmobileを使ってみる
Ad

Rust Error Handling

  • 1. Mobility Technologies Co., Ltd. Rust Error Handling 2021/04/28 @MoT.rs Shunsuke Nakamura AI技術開発部
  • 2. Mobility Technologies Co., Ltd. 今日やること 2 - Rustのエラー表現
 - エラーによるフロー制御
 - よくあるエラー処理
 - エラー時の早期リターン
 - ライブラリを使用したエラー処理のベストプラクティス

  • 3. Mobility Technologies Co., Ltd. Rustのエラー表現 3 ■ Rust には Java や Python のような例外はなく、Result型でエラーを表現する ■ Result型は Result<{Ok の時の中身の型}, {Errの時の中身の型}> で定義する ■ 実体はただのEnum型
  • 4. Mobility Technologies Co., Ltd. 問題1 4 Rust playground にかかれているコードのコンパイルエラーを解消してください
  • 5. Mobility Technologies Co., Ltd. 解説1 5 Okの際には i32 を、Err の際には ZeroDivisionError を返しているため、 ここでは Result<i32, ZeroDivisionError> を返せば良い
  • 6. Mobility Technologies Co., Ltd. エラーによるフロー制御 6 Result型に対して、OkとErrで処理を分けたい場合 Result型はenumなので簡単なパターンマッチングで処理を分岐させられる ※ enumのVariantによるフロー制御
  • 7. Mobility Technologies Co., Ltd. 問題2 7 Rust playground にかかれているコードのコンパイルエラーを解消してください ヒント 1. Result<T, E>はOk<T>とErr<E>のenum型です 2. enum & パターンマッチによるフロー制御はスライドの前ページを参照してください
  • 8. Mobility Technologies Co., Ltd. 解説2 8 Okの際は改めて中身を val として受けて表示し、 Errのときは _ で受けてエラーメッセージを出しています(eprintln! 等を使うとなお良い) _ で受けると「この変数は使用しない」ということを意味します 参考
  • 9. Mobility Technologies Co., Ltd. よくあるエラー処理 9 ■ 毎回パターンマッチを書くのは面倒。よくある処理はより短いメソッドを用意してくれている ■ unwrap: Okなら中身の値を取り出し、Errなら終了する。頻出 ■ 問題点として、Errだと本当にpanic終了してしまうので、そこでコードが落ちる。 ■ 本当に落として良いところでしか使ってはいけない ■ expect: Okなら中身の値を取り出し、Errならメッセージを付けて終了する ■ 問題点として、Errだと本当にpanic終了してしまうので、そこでコードが落ちる。 ■ 本当に落として良いところでしか使ってはいけない ■ and_then: Okなら後段の処理を継続し、ErrならErrを伝播させていく ■ 例外処理を上段に任せて正常ケースだけ処理を進めていく時に便利
  • 10. Mobility Technologies Co., Ltd. 問題3 10 Rust playground にかかれているコードのコンパイルエラーを解消してください ヒント Result型に用意されているメソッド一覧です https://doc.rust-lang.org/std/result/enum.Result.html
  • 11. Mobility Technologies Co., Ltd. 解説3 11 答え unwrap, expect, and_then をそれぞれで使います and_thenの中では次に実行するfunctionを渡してあげる必要があるので、 closure形式で渡しています
  • 12. Mobility Technologies Co., Ltd. 早期リターンと?演算子 12 メソッドの中で使用している値がOkなら値を取り出して、Errなら早期returnする、というコードをよく書くこと がある 下のようにパターンマッチを書いてもいいが、毎回これを書くのは面倒なので、 syntax sugarとして、?演算子が用意されている
  • 13. Mobility Technologies Co., Ltd. 問題4 13 Rust playground にかかれているコードのコンパイルエラーを解消してください
  • 14. Mobility Technologies Co., Ltd. 解説4 14 ? を使って Err 時に早期 returnさせます。 もちろん match を使って早期 return させてもいいですが、? のほうが短く済むし、見やすいです
  • 15. Mobility Technologies Co., Ltd. 複数のErrorを扱う 15 文字列 a, b を受け取って、i32型としてパースした後に割り算を行う関数を書いたとする これは以下のコンパイルエラーとなる。
  • 16. Mobility Technologies Co., Ltd. より正確な?演算子 16 ?演算子は受け取ったErr<E1>と、returnすべきErr<E2>が異なる時(E1 != E2のとき)、 型通りにreturnできるよう、E1をE2に型変換しようとしてくれる(同じ時は同じ型に変換する) RustでのA → Bへの変換は、Bに対してFrom<A> trait が実装されていれば - let a: A = From::from(B); - let a = A::from(B); のように行うことができる つまり、?演算子はより正確には↓となる
  • 17. Mobility Technologies Co., Ltd. 複数のErrorを扱う 17 文字列 a, b を受け取って、i32型としてパースした後に割り算を行う関数を書いたとする これは以下のコンパイルエラーとなる。 ParseIntError -> &str への変換が実装されていない!
  • 18. Mobility Technologies Co., Ltd. 問題5 18 Rust playground From traitを実装してください
  • 19. Mobility Technologies Co., Ltd. 解説5 19 答え From traitの実装はこのドキュメントに詳しいです。 impl From<変換元> for 変換先 … という実装をしておくと、 変換先::from(変換元) ができるようになります 余談ですが、この実装をすると自動で Into<変換先> for 変換元 が実装されるので、 let a: 変換先 = 変換元.into() が実行できるようになります
  • 20. Mobility Technologies Co., Ltd. 問題6 20 Rust playground From traitを実装して早期returnしてください
  • 21. Mobility Technologies Co., Ltd. 解説6 21 答え 先程と同様にFrom traitを実装します これのおかげで、早期returnの?演算子がFrom::from変換を呼び出すことができます
  • 22. Mobility Technologies Co., Ltd. 複数のErrorを扱う 22 一つの関数から複数のエラー(Err<E1>, Err<E2>, ...)が返る可能性がある、ということはよくある 対策としては、 - MyErrorのようなenumを定義し、全てのE1, E1→ MyError への変換(From)を実装する - 自分で定義したエラー型に、毎回変換を実装ていくのは面倒 - Result<T, Box<dyn Error>> を返す関数である、と定義する - Box<dyn Error> は Error traitを実装した任意の型、を意味する - 自分で定義したエラー型に、毎回Error traitを実装していくのは面倒 → 最近の主流: Error周りをよしなにやってくれる便利ライブラリを使う - anyhow: アプリケーション用と言われている - thiserror: ライブラリ用と言われている
  • 23. Mobility Technologies Co., Ltd. anyhow 23 アプリケーション用Errorライブラリ - anyhow::Errorの提供 - Box<dyn Error> のようなものになっており、 std::error::Errorを実装しているものなら何でも渡せる - Err(anyhow::anyhow!(“”)) だけで anyhow::Errorを生成してくれる - anyhow::Resultを提供 - anyhow::Result<T> だけで Result<T, anyhow::Error> と同じ意味になる - anyhow::Contextの提供 - 既存のErrorにメッセージを足すことができる
  • 24. Mobility Technologies Co., Ltd. thiserror 24 ライブラリ用Errorライブラリ - thiserror::Errorの提供 - 独自で定義したstructやenumに対して thiserror::Errorをderiveさせるだけで、 std::error::Errorを実装させることができる - anyhowと組み合わせることで かなりコード量を削ることができる
  • 25. Mobility Technologies Co., Ltd. 問題7 25 Rust playground anyhow / thiserrorを使ってコードを修正してください
  • 26. Mobility Technologies Co., Ltd. 解説8 26 まずは、std::error::Errorを実装した任意の型を返せるように変更する 途中経過1 しかしこれは残念ながらコンパイルエラーになる。理由は自分で定義したMyErrorがstd::error::Errorを実 装していないから(このstructはDebugしか実装していない) 自分でstd::error::Errorを実装するのは面倒なので、thiserrorを呼び出し、deriveさせるだけで実装したこ とにしてしまう 途中経過2 最後に、Result<i32, Box<dyn std::error::Error>> がやや長ったらしいので、これを略記できる anyhowを使って完成 答え
  • 27. Mobility Technologies Co., Ltd. 参考ページ 27 ■ Rust公式docs Error Handling ■ Rust by example Error Handling ■ Rustlings Error Handling ■ thiserror / anyhow の導入の流れ: Rust エラー処理2020