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

unwrap, expect, panic!, assert! をいつ使うべきか、どういう意味で読んでいるか等。 雑にツイット集めただけなので誰か整理してくれ〜
3
前へ 1 2 3 ・・ 7 次へ
Ryusei @mandel59

手抜きでNoneを返したのか、仕様に沿ってNoneを返したのか、区別できないな……

2020-12-22 17:00:48
Ryusei @mandel59

仕様か?バグか?それとも手抜き?

2020-12-22 17:01:34
Ryusei @mandel59

手抜きって仕様でもバグでもない。強いて言えば仕様だけど、最終的な仕様ではなく、一時的な仕様で、将来的に取り除かれるものだ。あー、unimplementedって用語があるか。

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

Rust だとそもそも Option にせよ Result にせよ「検査をしないことが許されない」というシステムがあって、その上で「検査が手抜きであるか否か」のレイヤーで葛藤が発生するので、いずれにせよ検査すること自体は変わらないのよな。 .unwrap() は「手抜き検査」として優秀なラベルになっている

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

で、 .expect() を手抜き検査として使えるべきかというと、まあ微妙なんだけど私としてはせめて「お前(ユーザ)が悪い」か「俺(expect を書いた人)が悪い」くらいの情報は籠めてほしい、最低限それがあれば手抜きではないよと言い訳もできる、くらいのお気持ち。

2020-12-22 17:04:05
Ryusei @mandel59

Rustにはunimplemented!マクロがあるので、それを使えば未実装というお気持ちを載せられそう

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

無論 .expect() でそこそこちゃんとした理由説明があればかなり有り難いし、自分で書くときは必ずそのようにしているけど

2020-12-22 17:04:26
Ryusei @mandel59

Rustのexpect、名前が悪いってずっと思っている……

2020-12-22 17:04:56
とりさん @TypedTypelessTy

@lo48576 はい.起こらない理由も(それが特別分かりにくい場合以外は)重要ではない.と考えています. 実装側のミスなのか,利用側のミスなのかは明確に分けて書くべきというのは賛成です.

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

で、そういう使い分けをすると「手抜きなら .unwrap()、ちゃんと考えたなら .expect()」という分類をもとにコードを読むときの注目を配分できるわけで、読むときにも嬉しいでしょうと

2020-12-22 17:05:42
Ryusei @mandel59

expect、手抜き用じゃない?

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

で、私が常々思っているのは「手抜きであるか否か」のラベルだけでなく、もう一次元加えて「お前が悪いか俺が悪いか」も名前とかで表明できてほしい、ということですね たとえば unreachable!() は「俺が悪い」を的確に表明できていてとても良い名前だと思うわけ

2020-12-22 17:06:39
Ryusei @mandel59

unwrapはメッセージも表示しないんだし、それは絶対通るって確信をもってやるでしょ

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

まあ理想的には match foo { Ok(v) => v, Err(e) => {/*ここで panic! なり unreachable! なりを使う*/} } なり .unwrap_or_else(|e| /* panic! や unreachable! */) を使いたいという立場では .expect() は手抜きなんだけど、じゃあ実際これを人々に求めるかというのは……

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

ちょっとコストが高すぎるというか、よーするに「これらの記法を .expect() 並に短かく表現できる、意味付けされたクラッシュが欲しい」というのが私の欲求です

2020-12-22 17:08:48
Ryusei @mandel59

Rust, unimplementedと別にtodoマクロがあって、あとでやるつもりがあるときはそっちを使うことができるっぽい。細かい

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

fn expect(&self, msg: &str) -> T の代わりに、 fn unwrap_which_must_always_succeed(&self, msg: &str) -> T と fn unwrap_or_panic(&self, msg: &str) -> T が欲しいと、私はそう言いたいわけです

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

twitter.com/lo48576/status… twitter.com/lo48576/status… この2つだな、私が今日言いたかったことは

2020-12-22 17:11:05
らりお・ザ・.*🈗然㊌㋞㋰㋷㋓ @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

ついでに .expect() だけでなく assert 系についても「俺が悪い」と「お前が悪い」の2種類あると嬉しいな、というよく似た話が twitter.com/lo48576/status… と twitter.com/lo48576/status… ですね。本質的には同じ欲求。

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

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

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

/// Asserts that a boolean expression is `true` at runtime, as the specification. macro_rules! spec_assert { ($($toks:tt)*) => { assert!($($toks)*) }; } みたいなのは考えたことあるんですよ。 「仕様としてのクラッシュを assert 的に雑に書きたい」という。

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

twitter.com/lo48576/status… 「俺が悪い」と「お前が悪い」で意味付けされた2種類の .expect() が存在すれば、意味付けされていない .expect() を手抜きとして使うことができるので、全てが解決して世界に平和が訪れる、と…… (バグが消えるとは言ってない)

2020-12-22 17:13:57
Ryusei @mandel59

そもそも型システムを使う意味が薄くなるから極力パニくらない方向にしてほしい

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

この辺りもアレで、そりゃ可能ならもちろん静的保証をしたいんだけど、それが無理で .unwrap() が必要になって、である以上は実装バグや仕様バグの可能性が否定しきれないので、「否定しきれないものの存在を否定するな」のお気持ちで起きえないブランチのエラーメッセージを考えているというところが

2020-12-22 17:15:25
Ryusei @mandel59

手抜きする方が面倒くさいのであれば、手を抜かないのが一番

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

方向性としては、そういうのを module や crate として分離していって、ライブラリの API としては基本的に panic や unwrap なしに使えるようにするのが良いのだろうけど、境界を切って封じられる unwrap ばかりとも限らないからなぁ

2020-12-22 17:16:50
Ryusei @mandel59

Rust使いたい時点でわりとカッチリしていないと気がすまない用途である気がするし、カッチリするのが一番ではないか(カジュアルRustも探求できるかもしれないが……)

2020-12-22 17:17:02
前へ 1 2 3 ・・ 7 次へ