Rust での unwrap, expect, panic, assert 周辺の話
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:02github.com/blas-lapack-rs… ピピー! unwrap 警察です! .unwrap() の代わりに .expect("エラーにならない理由") を使いましょう!!!
2020-12-22 15:16:21そういえば WalkDir のイテレータが返す DirEntry は relative path を返すメソッドがあってもおかしくないと思うんだけど、そうしない理由はあるのかな (内部実装的にはフルパスで持ってるからとか?)
2020-12-22 15:22:15std::fs::DirEntry - Rust doc.rust-lang.org/stable/std/fs/… std の DirEntry が full path しか返してくれないから、それを模倣してるのかな
2020-12-22 15:24:15ReadDir とか WalkDir が唐突に root として渡したパスと異なるプレフィックスを持つパスを返しはじめたらかなり怖いんだけど、実際それが起きないという保証がどこにもないんだよな……
2020-12-22 15:30:16書いてる時点でエッジケースが想像できてるなら、例としてコメントなりドキュメントなりで紹介してほしいというのが正直な気持ちではある
2020-12-22 15:30:50これは文脈次第だと思っていて、「クラッシュする可能性がある (何かあったときクラッシュするのが仕様である)」場合はエラーとなった理由を書くし、「クラッシュしえない (クラッシュしたら実装のバグである)」場合はエラーになりえない理由を書くようにしている twitter.com/Linda_pp/statu…
2020-12-22 16:24:04foo.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どうしても後者の意味にしたいときは foo.unwrap_or_else(|e| unreachable!("hoge: {}", e)) みたいな書き方にすることもあるけど、ちょっとくどいので、やっぱり楽して .expect("hoge") になることはままある
2020-12-22 16:26:20assert にも同様の濫用があって「クラッシュは仕様」と「クラッシュしたらバグ」が混在していて、その辺りは昔ブログに書いた: blog.cardina1.red/2019/12/19/don… > つまり、あらゆる assert は、プログラムが完全に想定 (仕様) 通りに動いたとするなら全く存在しなくても構わないように使うべきである。
2020-12-22 16:28:11個人的な考えでは assert は「クラッシュしたらバグ」でのみ使うべきだと思っていて、「不正な何かがあったら仕様としてクラッシュする」のときは if と panic!() を使うようにしている
2020-12-22 16:28:51SQLiteっぽい sqlite.org/assert.html twitter.com/lo48576/status…
2020-12-22 16:31:26sqlite.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:09twitter.com/lo48576/status… 起きえない理由を書くにも一応 "Should never happen since ..." とか "This must be always `Some(_)` because ..." みたいな文章にして、エラーの原因説明とは明確に区別できるようにしてる
2020-12-22 16:35:30pub fn from_index(index: usize) -> Self { assert!(index < std::u32::MAX as usize); みたいに入力値に対してassert使ったらぶちころがされる
2020-12-22 16:38:33SQLite の assert の記事、昔読んだような記憶があるので、影響されたのかもしれない (影響されやすいオタクなので)
2020-12-22 16:39:57