SlideShare a Scribd company logo
1 of 27
Download to read offline
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

What's hot

エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織Takafumi ONAKA
 
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
実運用して分かったRabbit MQの良いところ・気をつけること #jjug実運用して分かったRabbit MQの良いところ・気をつけること #jjug
実運用して分かったRabbit MQの良いところ・気をつけること #jjugYahoo!デベロッパーネットワーク
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)Takuto Wada
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところY Watanabe
 
Spring 5でSpring Testのここが変わる_公開版
Spring 5でSpring Testのここが変わる_公開版Spring 5でSpring Testのここが変わる_公開版
Spring 5でSpring Testのここが変わる_公開版Yuichi Hasegawa
 
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~ CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~ SEGADevTech
 
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)mosa siru
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかKoichiro Matsuoka
 
シリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかシリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかAtsushi Nakada
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)Yoshitaka Kawashima
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するYoshifumi Kawai
 
Cognitive Complexity でコードの複雑さを定量的に計測しよう
Cognitive Complexity でコードの複雑さを定量的に計測しようCognitive Complexity でコードの複雑さを定量的に計測しよう
Cognitive Complexity でコードの複雑さを定量的に計測しようShuto Suzuki
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなKentaro Matsui
 
人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with KarateTakanori Suzuki
 
ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門増田 亨
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐkwatch
 
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)NTT DATA Technology & Innovation
 

What's hot (20)

エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
 
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
実運用して分かったRabbit MQの良いところ・気をつけること #jjug実運用して分かったRabbit MQの良いところ・気をつけること #jjug
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
 
Spring 5でSpring Testのここが変わる_公開版
Spring 5でSpring Testのここが変わる_公開版Spring 5でSpring Testのここが変わる_公開版
Spring 5でSpring Testのここが変わる_公開版
 
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~ CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
 
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
 
SREチームとしてSREしてみた話
SREチームとしてSREしてみた話SREチームとしてSREしてみた話
SREチームとしてSREしてみた話
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
 
Oss貢献超入門
Oss貢献超入門Oss貢献超入門
Oss貢献超入門
 
シリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかシリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのか
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
Cognitive Complexity でコードの複雑さを定量的に計測しよう
Cognitive Complexity でコードの複雑さを定量的に計測しようCognitive Complexity でコードの複雑さを定量的に計測しよう
Cognitive Complexity でコードの複雑さを定量的に計測しよう
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate人生がときめくAPIテスト自動化 with Karate
人生がときめくAPIテスト自動化 with Karate
 
ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
 
Mavenの真実とウソ
Mavenの真実とウソMavenの真実とウソ
Mavenの真実とウソ
 
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
Grafana LokiではじめるKubernetesロギングハンズオン(NTT Tech Conference #4 ハンズオン資料)
 

Similar to Rust Error Handling

Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
Kanazawa.js.Next
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Nextdynamis
 
JJavaプログラム実行の仕組みと、高速・安定動作に向けた取り組み
JJavaプログラム実行の仕組みと、高速・安定動作に向けた取り組みJJavaプログラム実行の仕組みと、高速・安定動作に向けた取り組み
JJavaプログラム実行の仕組みと、高速・安定動作に向けた取り組み日本Javaユーザーグループ
 
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」
Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」fukuoka.ex
 
The Next Generation for C# Developers
The Next Generation for C# DevelopersThe Next Generation for C# Developers
The Next Generation for C# DevelopersTakayoshi Tanaka
 
JavaScript.Next
JavaScript.NextJavaScript.Next
JavaScript.Nextdynamis
 
Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~Unity2015_No10_~UGUI&Audio~
Unity2015_No10_~UGUI&Audio~CHY72
 
2008.10.18 L4u Tech Talk
2008.10.18 L4u Tech Talk2008.10.18 L4u Tech Talk
2008.10.18 L4u Tech Talkmitamex4u
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„和弘 井之上
 
JavaScript.Next Returns
JavaScript.Next ReturnsJavaScript.Next Returns
JavaScript.Next Returnsdynamis
 
第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめhakoika-itwg
 
はこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストはこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストSeiji KOMATSU
 
nadoka さんの m17n 対応のベストプラクティス
nadoka さんの m17n 対応のベストプラクティスnadoka さんの m17n 対応のベストプラクティス
nadoka さんの m17n 対応のベストプラクティスKazuhiro Nishiyama
 
Swift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswiftSwift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswiftTomohiro Kumagai
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„和弘 井之上
 
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALVisual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALegtra
 
こんな辛いテストはいやだ
こんな辛いテストはいやだ こんな辛いテストはいやだ
こんな辛いテストはいやだ Takuya Mikami
 
Jpmobileを使ってみる
Jpmobileを使ってみるJpmobileを使ってみる
Jpmobileを使ってみるHiromu Shioya
 

Similar to Rust Error Handling (20)

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

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