編集可能
2020年12月22日

Rust での unwrap, expect, panic, assert 周辺の話

unwrap, expect, panic!, assert! をいつ使うべきか、どういう意味で読んでいるか等。 雑にツイット集めただけなので誰か整理してくれ〜
3
てらモス♋️ @termoshtt

Rewrite anyhow to thiserror in openblas-build by termoshtt · Pull Request #50 · blas-lapack-rs/openblas-src github.com/blas-lapack-rs… なんか最近前日寝る前の記憶が若干曖昧なんだけど、このPR作っとるな...

2020-12-22 15:10:02
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

github.com/blas-lapack-rs… ピピー! unwrap 警察です! .unwrap() の代わりに .expect("エラーにならない理由") を使いましょう!!!

2020-12-22 15:16:21
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

なんでやろと思って上の方に遡ったら walkdir で、まあそりゃそうだねとなった (それはそう)

2020-12-22 15:16:53
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

そういえば WalkDir のイテレータが返す DirEntry は relative path を返すメソッドがあってもおかしくないと思うんだけど、そうしない理由はあるのかな (内部実装的にはフルパスで持ってるからとか?)

2020-12-22 15:22:15
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

std::fs::DirEntry - Rust doc.rust-lang.org/stable/std/fs/… std の DirEntry が full path しか返してくれないから、それを模倣してるのかな

2020-12-22 15:24:15
てらモス♋️ @termoshtt

Rust の Path 回りはなんか OS のパスがどうなってるかをあんまり信用してなくて保守的な API しか無いイメージ

2020-12-22 15:26:02
白山風露 @kazatsuyu

ジッサイあんまり信用できない(特にNTFS)

2020-12-22 15:28:18
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

ReadDir とか WalkDir が唐突に root として渡したパスと異なるプレフィックスを持つパスを返しはじめたらかなり怖いんだけど、実際それが起きないという保証がどこにもないんだよな……

2020-12-22 15:30:16
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

書いてる時点でエッジケースが想像できてるなら、例としてコメントなりドキュメントなりで紹介してほしいというのが正直な気持ちではある

2020-12-22 15:30:50
ドッグ @Linda_pp

Result::expect の引数ってエラーになった理由を書くもんだと思ってる

2020-12-22 16:18:41
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

これは文脈次第だと思っていて、「クラッシュする可能性がある (何かあったときクラッシュするのが仕様である)」場合はエラーとなった理由を書くし、「クラッシュしえない (クラッシュしたら実装のバグである)」場合はエラーになりえない理由を書くようにしている twitter.com/Linda_pp/statu…

2020-12-22 16:24:04
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

foo.expect("hoge") が match foo { Ok(v) => v, Err(e) => panic!("hoge: {}", e) } である場合と match foo { Ok(v) => v, Err(e) => unreachable!("hoge: {}", e) } である場合があって、 .expect() はそれらのどちらにも使える雑なメソッドであるともいえる

2020-12-22 16:25:25
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

どうしても後者の意味にしたいときは foo.unwrap_or_else(|e| unreachable!("hoge: {}", e)) みたいな書き方にすることもあるけど、ちょっとくどいので、やっぱり楽して .expect("hoge") になることはままある

2020-12-22 16:26:20
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

assert にも同様の濫用があって「クラッシュは仕様」と「クラッシュしたらバグ」が混在していて、その辺りは昔ブログに書いた: blog.cardina1.red/2019/12/19/don… > つまり、あらゆる assert は、プログラムが完全に想定 (仕様) 通りに動いたとするなら全く存在しなくても構わないように使うべきである。

2020-12-22 16:28:11
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

個人的な考えでは assert は「クラッシュしたらバグ」でのみ使うべきだと思っていて、「不正な何かがあったら仕様としてクラッシュする」のときは if と panic!() を使うようにしている

2020-12-22 16:28:51
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

こういうとき自己引用できて楽なので、記事にして残しておくのは大事だなぁと思う

2020-12-22 16:30:28
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

sqlite.org/assert.html#ph… > An assert(X) should not be seen as a safety-net or top-rope used to guard against mistakes. Nor is assert(X) appropriate for defense-in-depth. ふむ

2020-12-22 16:34:09
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

twitter.com/lo48576/status… 起きえない理由を書くにも一応 "Should never happen since ..." とか "This must be always `Some(_)` because ..." みたいな文章にして、エラーの原因説明とは明確に区別できるようにしてる

2020-12-22 16:35:30
Ryusei @mandel59

SQLiteでのassertの使い方は一番厳格なんだね

2020-12-22 16:36:31
Ryusei @mandel59

pub fn from_index(index: usize) -> Self { assert!(index < std::u32::MAX as usize); みたいに入力値に対してassert使ったらぶちころがされる

2020-12-22 16:38:33
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @lo48576

SQLite の assert の記事、昔読んだような記憶があるので、影響されたのかもしれない (影響されやすいオタクなので)

2020-12-22 16:39:57
denjiry @denjiry

むしろexpectを仕様としてpanicするほうに使いたくない気持ち

2020-12-22 16:41:11
Ryusei @mandel59

D言語の場合は契約プログラミングで、事前条件の中に出てくるassertは呼び出し側が守る必要がある条件

2020-12-22 16:41:24
残りを読む(148)

コメント

コメントがまだありません。感想を最初に伝えてみませんか?