23/01/17 12:41:51.84 esjs4yiD.net
たておつ
3:デフォルトの名無しさん
23/01/17 14:00:56.91 MqwPrlrO.net
89 それでも動く名無し 2023/01/10(火) 23:26:51.53 ID:pA5+SQtP0
痴漢ものAVと違ってこういうガチ痴漢は臨場感が違うわ
抵抗されて上手く行かなかったり、たまに他の客にバレて逃走してるからな
マジで興奮する
URLリンク(i.imgur.com)
URLリンク(i.imgur.com)
URLリンク(i.imgur.com)
URLリンク(gcolle.net)
520 名無しさん@ピンキー sage 2023/01/03(火) 21:36:57.85 ID:AS4vmq4R0
不朽の名作が復活していたので
URLリンク(i.imgur.com)
URLリンク(i.imgur.com)
URLリンク(gcolle.net)
4:デフォルトの名無しさん
23/01/17 14:01:08.20 MqwPrlrO.net
すみません、誤爆しました
5:デフォルトの名無しさん
23/01/17 14:04:39.15 QD1aLS8A.net
. :::';;;;: . . ..,,,;;:
. . :;;;;;:.:;;,, ..:.;;;;.:
:;;''' .:';;; . . .:.:;;;;;':. . . .,,,,;,,...,,
.:;;;' : .:;;;;; .: ,,,;;;,,, , .:;;;';;''' ''';;;;,,
. :.;;;;' . .: ;;;;;;;;'''' ';;;:.:.. ,;: . . ''''''"
';;:;' ''''; .:.';;;;,,;;.
''' ,.:.:';;;;,,,,
,、—-、 .;.';:;.:.: ;;;;;;:.;.;...
-、_ (_二ニ=っ,、;;;:.:;.:;...:.:...'''''''''''
`‐-、_ ( ´∀)f、 `''、:..:.:. .:
`-,ノ つ; /
(〇 〈-`'"
(_,ゝ ) `‐-、_
(__) `'‐-、,_..
`‐-、._
6:デフォルトの名無しさん
23/01/17 14:25:12.33 IvlgRnTP.net
ここが新しいおちんぽスレと聞いて
7:デフォルトの名無しさん
23/01/17 14:31:29.73 AjT+2M0N.net
最低だな
犯罪者予備軍やん
8:デフォルトの名無しさん
23/01/17 16:35:46.70 +0g0VEsU.net
通報しといたよ
9:デフォルトの名無しさん
23/01/17 16:41:04.96 mmIRzxLT.net
はよ立て直せ
10:デフォルトの名無しさん
23/01/18 10:59:16.69 j7LzfbP6.net
ワッチョイ有効スレ
スレリンク(tech板)
11:デフォルトの名無しさん
23/01/18 12:30:23.66 NvrWVfIW.net
おちんぽまんまんスレ違いと聞いて
12:デフォルトの名無しさん
23/01/18 20:15:50.70 CRD98AUE.net
ResultがErrの時だけブロックを実行するifってどうやって書けばいいの?
if Err(_) = fs::read_to_string("foo.txt") { err() }
は通らないようだが
13:デフォルトの名無しさん
23/01/18 20:29:34.91 vXgVoSzN.net
if let Err(_)
14:デフォルトの名無しさん
23/01/18 20:41:58.72 CRD98AUE.net
>>13
サンキュー。行けた
15:デフォルトの名無しさん
23/01/19 04:27:00.05 UpsgRjC+.net
>>12
エラーが起きた時は先に判断してreturnして
そうでなく正常値が得られた時はlet代入してインデントを下げずに書けないかな?
16:デフォルトの名無しさん
23/01/19 07:51:52.20 kHXiKnOP.net
>>15
それが少し前に入ってみんな喜んでた let else だね。
let Ok(value) = result else { return };
/* Ok のときやりたい処理 */
みたいにエラーは早期リターンして、正常系をインデント下げて書くみたいなことができる。
俺は Err は anyhow で呼び出し側に返しちゃう事が多いから正直あまり使わないけど。
17:デフォルトの名無しさん
23/01/19 10:36:41.67 pws6L0p3.net
Option/Result系は?演算子で素直に返すしそれ以外でもResultを返す関数に切り出して呼び出し側で?演算子にするからlet-elseは使い所がよく分からん
18:デフォルトの名無しさん
23/01/19 11:05:24.00 MVgEnHGb.net
>>15
そもそもreturnしない。err()の中身はエラーメッセージを出力後にパニックさせるので一方通行
19:デフォルトの名無しさん
23/01/19 13:52:46.10 i8wJP128.net
expectじゃだめなのかな?
もう少しちゃんとしたロギングをしたいならlog crate使ってlog_expectみたいな形でunwrap
20:デフォルトの名無しさん
23/01/19 14:21:48.46 plizw9iy.net
自分で書いといてあれだからやっばりexpect使うケースじゃないな
panicさせるよりもErrのまま最上位まで返してそこでログ出力含めてハンドリング
21:デフォルトの名無しさん
23/01/19 18:44:58.53 kHXiKnOP.net
expectってライブラリの動作確認とかサンプルコードとか、トップレベルで雑なことしたいとき以外使わなくない?
深めの階層で見かけたら身構えちゃいそう。
22:デフォルトの名無しさん
23/01/19 19:25:25.54 UlqzrrZi.net
論理的に安全にunwrapできるってわかってる箇所には使うかな
もしパニックになるならそもそも致命的な論理バグがあるってことになるから
変にエラー処理するより早期に落とした方がいいってケース
23:デフォルトの名無しさん
23/01/19 20:03:32.07 KyLvYp+m.net
横からですまんが安全なら unwrap() でよくない?
expect() にする理由ってなんだろう
24:デフォルトの名無しさん
23/01/19 20:30:48.24 UlqzrrZi.net
個人的には Regex::new(r"").unwrap() みたいに自明ならunwrap
安全にunwrapできる理由を書きたいならコメントに書くよりexpectに書くかな
25:デフォルトの名無しさん
23/01/19 20:45:59.09 kHXiKnOP.net
なるほどね。自明な時に unwrap したいけど、仮に起きたときに原因調査しやすいよう expect というのは納得できる。
26:デフォルトの名無しさん
23/01/19 20:51:26.80 kHXiKnOP.net
あ、違うか。unwrapできる理由を書くわけか。
paniced at 'ここでは 0 は渡ってこないので自信を持って除算する'
みたいな出力になるから割と恥ずかしいな。
27:デフォルトの名無しさん
23/01/19 21:03:13.60 KyLvYp+m.net
>>26
これは俺も思ったw
まぁ自分しか使わないライブラリとかならいいかもね
28:はちみつ餃子
23/01/19 22:24:19.09 uAmZfzQm.net
>>27
自分意外が使う前提のときのほうが except が必要だと思う。
外部から与えられる情報が仕様外の場合 (事前条件が満たされない場合) など
使い方が誤っているときに起こりえるなら except で説明があったほうがいいんじゃない?
内部的なロジック的に起こりえないと確信しているところは unwrap でいいと思う。
間違いがあったときに panic! してくれることには変わりないしバックトレースも出せるんで、
特に必要だと思う箇所だけ説明を付けておけば十分でしょ。
29:デフォルトの名無しさん
23/01/19 22:58:51.51 TbDEskmg.net
>>26
関係ないけどpanicに-ed、-ingつけるとkが差し込まれてpanicked、panickingになる
自分もRust触るまで知らなかった
30:デフォルトの名無しさん
23/01/20 00:14:17.87 +VmzUJ32.net
Optionを返す関数が2つ(以上)あり、
Someを得られるまで遅延評価で順に試す場合に、
func1(arg)
.or_else(|| func2(arg))
と非対称で手間なのを改善する方法ありますか?
例えば func1(arg) || func2(arg) と書けると便利だと思いました
31:デフォルトの名無しさん
23/01/20 00:47:21.47 sbzTb5wM.net
イテレータ化してchain()で繋げるとか?
でも手間は変わらないか
32:デフォルトの名無しさん
23/01/20 02:52:18.79 rWEP7xyW.net
>>30
ないんじゃね
何回も書く必要があるなら単に関数化する
||演算子で書きたければマクロ内独自文法作る
33:デフォルトの名無しさん
23/01/20 11:05:21.77 cF/QvtGv.net
>>20
今だいたいそうなっていてmainにエラー出力用のコードが散在している状態
エラーメッセージの出力先もコンソールのみじゃないのでexpectだと難しい気が
34:デフォルトの名無しさん
23/01/20 13:36:20.52 pmLm7hT0.net
ちんちん!シュッ!シュッ!!シュッ!!!
35:デフォルトの名無しさん
23/01/20 21:59:08.95 A12k25he.net
>>33
いろんな問題をごちゃ混ぜにしすぎ
頭とコードを整理しよう
36:デフォルトの名無しさん
23/01/21 14:16:15.90 tEFzN85r.net
1.すべてmainまで返してmainでエラー処理をする
2.エラー処理用の関数を作ってそれを呼び出す
3.パニックハンドラでエラーメッセージを出力
くらいしか思いつかん。ググってもThe Bookに書いてある程度のことしか出てこなくて参考にならない
3はpanic!やexpectで脱出できるのは楽だけどハンドラへ渡せるデータが文字列のみでなのがいまいち
またエラー処理に必要な情報を文字列にエンコードする必要がある
2ならmainまで戻らずともエラー処理できるのでこの方向で実装中
37:デフォルトの名無しさん
23/01/21 14:57:31.49 hb5eMxVX.net
log crateやtrace crateはチェック済み?
logは準標準、実装は好きなのを選ぶ必要がある
traceはtokio-rs製
38:デフォルトの名無しさん
23/01/21 16:41:16.71 3Tq4pZe4.net
>>32
|オペレータのstd::ops::BitOrトレイトのように
||オペレータのトレイトをRustコンパイラが用意してくれたらOptionも||で扱えそう
39:デフォルトの名無しさん
23/01/21 18:30:23.18 /bIQjlWu.net
>>37
info!やerror!ってpanic!やexpectと本質的に変わらないような。いずれにしろ呼び出し側で文字列の加工が必要
GUIへの対応方法もよくわからない。開発時はもちろんコンソールへの出力を使うけど
運用中のエラー出力はGUIのポップアップメッセージがメインになるし
あとソースコードは600行弱くらいだけどリリースビルドで生成されるバイナリは800KB弱もあるんで
これ以上でかくしたくないというのもある
40:デフォルトの名無しさん
23/01/21 22:40:10.67 wag66I/R.net
ロガーを設定/生成するコード
ロガーを使うコード
ロガー自体のコード
それぞれ分けて考える
ロガーを使うコードではファイル出力だろうが標準出力だろうがinfo!やerror!でコードを変える必要はない
使うロガーを変えたり設定を変えたりする
ロギングライブラリを使うのは自前で作るのは面倒だから
41:デフォルトの名無しさん
23/01/22 02:33:12.00 5IaN6zUW.net
書籍で最初に読むとしたら
平家蟹の方?
それとも可愛い方?
42:デフォルトの名無しさん
23/01/22 02:45:54.00 DAK16wxY.net
平家蟹がかわいくないとか、こいつアンチか?
43:デフォルトの名無しさん
23/01/22 02:46:40.77 4BdfAMug.net
>>39
>GUIへの対応方法もよくわからない。
GUIのレイヤーまでResultを戻してErrならエラー表示をするだけ
44:デフォルトの名無しさん
23/01/22 12:43:00.06 WLCvNrGP.net
>>39
ログはログ。何が起きたか記録するだけ。ログレベルが何であれ副作用は起こさない。
エラーはエラー。発生したときにどうハンドリングするかはプログラムの性質で決める。
パニックはそのまま稼働したらまずい状況に陥ったら時だけ起こす。
45:デフォルトの名無しさん
23/01/22 14:52:04.22 RMpOCJx1.net
>>41
モンタギュー蟹の方
46:デフォルトの名無しさん
23/01/22 15:29:33.81 WCVJRVcD.net
アプリケーションのレイヤーでパニック起こすのはバグの時だけ
47:デフォルトの名無しさん
23/01/25 16:19:44.22 zlgPT3s2.net
ネットワーク前提にしてる時に、panicになるのはバグではないよ?
48:デフォルトの名無しさん
23/01/25 16:35:00.31 LG3Fy/yw.net
うっわすっげー読みやすいコードと思ってよく見てみたら
過去に自分が書いたやつだった(´・ω・`)
49:デフォルトの名無しさん
23/01/25 16:39:27.19 5onhVltK.net
天才か?
50:デフォルトの名無しさん
23/01/25 16:40:49.73 GSIKYco3.net
過去の自分は他人だと思え、がプログラミングの基本
51:デフォルトの名無しさん
23/01/25 17:17:39.71 xORIlv/9.net
過去のことを忘れていても過去の自分が考えることは今の自分が考えることとあまり差がない。
名前の付け方とかは何度考えても同じような状況なら同じ名前を付けるし。
書くときに想定する読み手が全くの他人のときと未来の自分のときではちょっと違う意識があるな。
52:デフォルトの名無しさん
23/01/25 18:36:03.64 V9gmFqbx.net
一度も使ったことがない機能は書くことはできても読めると思うな、が基本
使ってから読め
53:デフォルトの名無しさん
23/01/25 19:53:08.97 sck5kayB.net
>>47
ネットワークこそ途中で途切れること前提に書かないといけない機能の最たるものだろ。エラー返してハンドリングしろ。
54:デフォルトの名無しさん
23/01/25 20:37:11.28 5EKz9Dxo.net
>>48
あるあるだね
55:デフォルトの名無しさん
23/01/25 20:38:19.94 xtWPaGBn.net
>>47
なんでpanicになるの?
56:デフォルトの名無しさん
23/01/25 21:43:02.36 jK9fbSTx.net
>>38
一度ポシャってるけど実装される可能性はあると思う
URLリンク(github.com)
57:デフォルトの名無しさん
23/01/25 23:55:49.39 7h2BZmgN.net
bool以外でも&&と||の遅延評価が使えるようになるわけか
欲しいね
58:デフォルトの名無しさん
23/01/26 00:47:59.28 Oik+f0Gv.net
bool以外でもifを使えるといえばif letで
elseを省略することで3項ではなく2項演算のようになるのも&&と同じ
だがelseを省略できても{}を省略できなければ意味がない
59:デフォルトの名無しさん
23/01/26 11:05:43.50 G0iCERKY.net
>>58
もうちょっと基礎を勉強してからレスしろ
60:デフォルトの名無しさん
23/01/26 11:09:10.89 QY5r5/0E.net
すまんが、これの解答はmutをつけろっていうことなのはわかるけどさ
URLリンク(github.com)
なんで8行目で所有権を失って9行目で代入できなくなったりしないの・・・・?
61:デフォルトの名無しさん
23/01/26 11:24:13.84 DDvWU5a2.net
>>60
これはもっともな疑問
The Bookのどこかに書いてたように思うけど
ざっくり言えばprintlnはreferenceを取るから所有権は移動しない
DisplayトレイトやDebugトレイトのメソッドシグニチャを見ると分かる
62:デフォルトの名無しさん
23/01/26 11:33:53.75 Y60o/Mze.net
>>60
ついこないだ Teratail で同じような質問を見たぞ。
マクロは構文糖を作り出す仕組みなので展開形によっては所有権を取ることも借用なことも何にも使いすらしないということもある。
63:デフォルトの名無しさん
23/01/26 14:03:27.91 YuUaXpq9.net
ある関数の&mut T型の引数として、T型の変数を貸すのは分かるけど
&mut T型の変数を又貸しするのが不思議
なぜmoveしたことにならないのか
64:デフォルトの名無しさん
23/01/26 15:25:17.84 MCrVnhV0.net
>>63
&TはCopyだからmoveしないよ
65:デフォルトの名無しさん
23/01/26 15:35:28.34 SkvAt80a.net
>>63
implicit reborrowのことかな?
&mut Tの又貸しと言ってるのがどういうケースなのかはコードかないハッキリはわからないな
66:デフォルトの名無しさん
23/01/26 17:21:49.46 YuUaXpq9.net
implicitly reborrowedされるとhogeが&mut *hogeになるのか
勉強になった
ありがとう
67:デフォルトの名無しさん
23/01/26 18:45:49.05 nglgEIPC.net
結局&mutを持っている間は専有しているから既存ルールに抵触することなく貸し出し自由自在という理解でいいのかな
&*でimmutableなreborrowも出来ちゃうもんね
68:デフォルトの名無しさん
23/01/26 19:48:43.33 16g2h/GU.net
>>60
変数が値を所有しているんだよ
値がムーブされて一度無効化された変数にも新しい値を所有させられるよ
例えば、その9行目でxが3を所有していなかったとしても新しい値を入れられるよ
URLリンク(play.rust-lang.org)
69:デフォルトの名無しさん
23/01/26 19:50:53.34 uBPDOaY+.net
暗黙で参照が外されることがあるからわかりにくいんだろうな
最初から暗黙の参照外しがなければよかったと思うが
後方互換性を大事にするなら、もう改善は不可能だな
70:デフォルトの名無しさん
23/01/26 20:31:02.62 q1WzF/2m.net
>>53
だからバグじゃないよね?
71:デフォルトの名無しさん
23/01/26 21:11:51.00 BacNCpeu.net
>>70
エラーを返すんだからpanicしないだろ
72:デフォルトの名無しさん
23/01/26 21:14:28.71 GObOayQz.net
>>68
そりゃmutならなw
73:デフォルトの名無しさん
23/01/26 21:18:17.56 q8T2WGhT.net
implicit reborrowはThe Bookには書かれないし直感的でもないから動きが理解しにくいというのはよく分かる
74:デフォルトの名無しさん
23/01/26 21:50:47.31 ZxPs9rBQ.net
>>70
例えばtwitterアプリを地下鉄とか通信できない状況で起動して panic で落ちる事を考えてみろ。そりゃバグだろ。
75:デフォルトの名無しさん
23/01/26 22:06:21.53 HEA6MC1t.net
Deref無しは流石にきついな
一気にRust書きたくなくなる気がする
76:デフォルトの名無しさん
23/01/26 22:20:38.36 nglgEIPC.net
>>69
むしろderef含めたcoercionのおかげでRustは便利かつ読みやすいと思う
初心者の最初のうちだけは混乱するかもしれないけどそのデメリットを誤差にするほどの絶大なメリットがある
77:60
23/01/27 11:24:22.85 CSClNfzp.net
教えてくれてるのは本当にありがたいんですが、訳がわかんないぽ・・・・
78:デフォルトの名無しさん
23/01/27 11:51:57.32 YDsF+xqw.net
>>77
何がわからないのか書いて
79:60
23/01/27 13:58:30.55 CSClNfzp.net
マクロが展開するコードがあって、そこに&がついてるってことなんですか?
80:デフォルトの名無しさん
23/01/27 14:00:09.55 MqPTrKVr.net
せやで
Playgroundの左上のボタンでShow HIRするとマクロ展開等終わった後のコード出るから見てみ
81:デフォルトの名無しさん
23/01/27 19:13:43.59 q2LYouLt.net
&はついてるけどあなたの疑問とは関係ないと思う
82:デフォルトの名無しさん
23/01/27 21:29:03.39 N1uoRX56.net
>>74
例がtwitterアプリって...通信が出来ない状態でも何らかのオフライン操作が行えるアプリであればそうでしょうが
仕様上、エラーハンドリングを行わなければならないとされていないならバグではないでしょ....
むしろ大したログやコンソールでの情報も出さず、「エラー:通信ができましぇん」なんて返されるほうが迷惑だわ
83:デフォルトの名無しさん
23/01/27 21:54:30.76 cQ0vJjwr.net
>>82
バグかどうかは仕様次第というのはそりゃそうなんだけど、それじゃ建設的な議論にならんでしょ。
俺はError返しといたほうが利用側がハンドリングする余地があっていいと思うね。
84:はちみつ餃子
23/01/28 02:45:04.16 OM0pptP0.net
>>82
Rust の文化にあまり詳しいわけじゃないけど panic を呼び出すのって C/C++ で言うところの assert 的なもんでしょ。
普通に考えたら panic が呼ばれるのはモジュールの仕様に対して使い方が間違っているかリカバリ不可能な場合。
逆に言えば使い方が正しくてリカバリ可能な状況で panic になるべきではない。
モジュールの使い方が完璧に正しいプログラムを書いても panic が引き起こされてしまうなら panic の使い方のほうが間違ってる。
絶対に通信が確立する状況で使えという仕様を設定すりゃあ間違ってるのは使い方のほうではあるけどさー、
ネットワークでそれは不可能な前提じゃん? ありえない前提を元にするのは不毛だろ。
85:デフォルトの名無しさん
23/01/28 07:46:19.92 NqcfPhRT.net
>>82
> 仕様上、エラーハンドリングを行わなければならないとされていないならバグではないでしょ....
仕様バグ...
86:デフォルトの名無しさん
23/01/28 09:58:07.00 40nYh31B.net
ユーザーにとって不自然な動作をすれば開発者が仕様だと言い張ったところでそれはバグだよ
87:デフォルトの名無しさん
23/01/28 10:54:36.16 9JWZ6Tol.net
エラーにも回復可能なエラーと不可能なエラーがあり、panicすると回復不可能な状態になるんだから、回復可能なエラーはpanicすべきじゃない。ましてや通常使用でしばしば発生する状態でpanicするのは言語道断だわな。
88:デフォルトの名無しさん
23/01/28 10:57:15.78 A5TUrW0u.net
assertというかexitやな。推奨はされん、普通はデバッグで面倒な時くらいじゃないか。
89:デフォルトの名無しさん
23/01/28 11:52:23.17 NqcfPhRT.net
>>86
MSの開発者を説得してくれ
90:デフォルトの名無しさん
23/01/28 11:54:06.56 NqcfPhRT.net
>>88
exitは正常終了でも呼ばれるからassertのほうが意味的には近いと思うぞ
91:デフォルトの名無しさん
23/01/28 14:06:35.25 qTYDIi6E.net
マルチスレッド界隈ではスレッドの一つや二つ終了しても
回復不可能と思ってないでしょ
92:デフォルトの名無しさん
23/01/28 14:59:51.08 pTjpQsNq.net
The Bookにある回復不可能かどうかという判断基準は曖昧であまり役に立たない
Resultを伝播させてトップレベルでログ出力でもしてabortさせるのに比べて
問題発生箇所でpanicさせるメリットは処理をinfallibleな関数として定義出来ること
逆に言えばバグでも無いのにinfallibleな関数呼び出しでpanicで落ちるような設計はそれ自体がバグの可能性大
93:デフォルトの名無しさん
23/01/28 17:20:49.61 qTYDIi6E.net
0か1かではなくバグが何個あるのかも重要
落とせば一つ?
進めれば二つ以上?
94:デフォルトの名無しさん
23/01/28 17:59:00.91 b6xT90Ev.net
>>93
イミフ
95:デフォルトの名無しさん
23/01/28 19:43:12.93 qTYDIi6E.net
>>86
開発者なんていないよ、みんなユーザーだよって言い張ったのがオープンソースだね
96:デフォルトの名無しさん
23/01/28 21:12:57.88 ZIiiTUHL.net
>>95
イミフ その3
97:デフォルトの名無しさん
23/01/28 22:16:55.89 qTYDIi6E.net
ユーザーと開発者を分断して対立煽るのをやめようってことだよ
98:デフォルトの名無しさん
23/01/28 23:41:24.90 j4/fJAgO.net
自分(たち)で用いるツール類だけは
自明な前提を満たしていない場合に限り
エラー処理をサボったpanicで終わらせてもよい
それ以外のpanicは状態矛盾など続行不可禁止で発生するが
正しくエラー終了させるべきものであり
panic発生はバグと呼んでも差し支えない
99:デフォルトの名無しさん
23/01/29 01:28:33.47 K5ah9cLk.net
>>98
panicをハンドリングしないのはバグかどうかは仕様次第と完全に認めてるのに、建設的な議論って・・・
作法的な話や、ユーザーフレンドリなUIでエラーメッセージを出したい、いきなり終了して欲しくないのであってもプロジェクトごとに異なるし、一般的な普遍性なんて「仕様上」に何が言いようがあるんだ?
オレはいつもこうしてます!という癖だったらいくらでも言えるし、100人集めてアプリケーションのレイヤーでpanicをハンドリングする/しないでアンケートしてどっちが人気かで正しさが決まるようなものではない。
最終的に「アプリケーションのレイヤーでパニック起こすのはバグの時だけ」とかいうのは明らかに間違ってるでしょ
そうするような特定のプロジェクトの仕様がたまたま(確率的に)一致するかもしれないが、それも一般化できる話ではないよ。
まあ、お望みの建設的な議論をするなら、アプリケーションをライブラリのように使用できる余地があるならResultsなどでErrorを返すのはとても良いですが、それでもpanicをハンドリングしてErrorで返すべきでは”無い”でしょうね
なぜならRustはそれを推奨していないし、Errorチェックしてをpanicに変換する方向性はあっても、panicをErrorに変える方向性は、仮にログ出力してもpanicの握り潰しやエラー情報の欠落に等しい。(なぜならログへのI/Oエラーになってる可能性もあるから)
それは、そもそもRustのpanicは言葉上は回復不能なエラーであり、バグではなくメモリーに物理的な障害が発生して配列インデックスが変になったとか、処理が続行できない、もしくはいったん特定の場所に戻って回復できないときに使われる思想。
なので、panic->Error変換処理が正常に働くかも怪しい。だからRustはそれを捉えず上位へ流して最低限やるスタックの巻き戻しのみ処理を推奨し、即座に終了させる(=プログラムが落ちる)
Linusはこのスタックの自動巻き戻しがとても気に入らないらしいが、理由は巻き戻し処理が正常に働く理由が無いからだ。
それを無理やり捉えて、スタックトレースが出るのが嫌、即座に終了するのが嫌、は分かるけどpanicで終了したからと言って仕様に書いてなければバグじゃないでしょ
これを癖でやってしまうのはtry-catch構文があるC#やJava系から来た人が多いのではないかな...?
100:デフォルトの名無しさん
23/01/29 02:35:07.62 r5isV+tS.net
誰もpanicをResultに変換する話はしとらんやろ
101:デフォルトの名無しさん
23/01/29 07:18:58.36 ksaPk66E.net
て言うか>>99は前半と後半で矛盾してるしアホほど長文を証明してるw
102:デフォルトの名無しさん
23/01/29 11:17:47.92 p51Kojpz.net
panicは仕様に書いてなければバグでしょ
どんなプログラム書いてんだよ
103:デフォルトの名無しさん
23/01/29 11:27:06.90 FaEg6ckP.net
エラーハンドリングという言葉をpanicをハンドリングしてResultにすることだと思ってたのか
そりゃ噛み合わないわな
104:デフォルトの名無しさん
23/01/29 13:10:21.68 ZDOIjMr/.net
例えばpythonのexitの代用としてpanicを使ったところで何の問題もない
105:デフォルトの名無しさん
23/01/29 14:45:33.86 ttNbSKVN.net
問題ありまくり
同じexitがあるのにわざわざpanicで代用するメリットは何?
106:デフォルトの名無しさん
23/01/29 15:29:55.13 yzACUqHq.net
まずは異常終了と正常終了を分断するメリットを知る必要がある
107:デフォルトの名無しさん
23/01/29 15:33:47.16 ZDOIjMr/.net
>>105
へー今初めて知った
The BookのCommon Programming Conceptsあたりにそれっぽい記述はないし
中断したければpanicするしかないと思っていたよ
後学のためにどこで解説されているのか教えてほしいな
108:デフォルトの名無しさん
23/01/29 15:48:49.58 CZoRokqJ.net
panic!すべきかするまいか
URLリンク(doc.rust-jp.rs)
109:デフォルトの名無しさん
23/01/29 17:07:54.00 qjfBPBdR.net
>>107
The Bookの12章を復習して
URLリンク(doc.rust-lang.org)
ただThe Bookは他言語から来た人が最初に読むチュートリアルとして用意されてるものなのでカバーされてない内容も多々あるし深い解説がされてるわけでもない点は理解しておいた方がいいよ
110:はちみつ餃子
23/01/29 17:16:49.84 2OIx0YXk.net
標準ライブラリのマニュアルでも panic! はバグを説明するために使うということは書いてあるね。
URLリンク(doc.rust-lang.org)
111:デフォルトの名無しさん
23/01/29 18:20:40.83 yP5ym/xP.net
>>107
exitはプロセスの終了状態コードを伝えることを兼ねたOSシステムコールだから通常の言語には必ずある
そしてそのことを分かっていればRust初心者であってもstd::process::exitをすぐに見つけられる
112:デフォルトの名無しさん
23/01/29 18:41:07.89 qSgQK/Ke.net
>>105
Pythonのsys.exitと同じ感覚でstd::process::exit使うほうがはるかに問題では?
少なくとも異常終了に使う分にはpanic!のほうがsys.exitに近いと思うよ
sys.exit()
URLリンク(docs.python.org)
・SystemExit例外を投げるだけ
・メインスレッドで実行して、かつ例外がトップレベルまで捕捉されなければ、通常の例外機構に従ってプロセスが終了する
→finallyとかwithでリソース解放書けばちゃんと解放される
std::process::exit()
URLリンク(doc.rust-lang.org)
・無条件でプロセスを終了させる
・実行スレッドも他のスレッドも一切スタック巻き戻しが行われない
→デストラクタ呼ばれない
113:デフォルトの名無しさん
23/01/29 18:45:14.86 jE2G9ZiM.net
_exit()はシステムコールだけどexit()はライブラリの関数
pythonのexit()やsys.exit()は基本的にexitcodeを設定してSystemExit例外を投げてるだけ
os._exit()がprocess::exit()に近い
114:デフォルトの名無しさん
23/01/29 18:46:31.90 jE2G9ZiM.net
>>112
例外のある言語と同じ感覚でプログラミングするのが一番の問題
それ抜きにpythonと比べとも意味ないよ
115:デフォルトの名無しさん
23/01/29 18:48:13.88 yP5ym/xP.net
一般的な他の言語におけるtry-throw-catchの機能が欲しいならば
それはRustやGoなどでは意図的に排除されていて存在しない
RustではResultで返すだけでよく利便性と効率を両立させている
116:デフォルトの名無しさん
23/01/29 19:53:25.69 ZDOIjMr/.net
>>109
そこは見ているけど制御機構を説明しているところで同時に解説すべきなのでは
>The Bookは他言語から来た人が最初に読むチュートリアルとして用意されてるもの
なおさら他言語でメジャーな機能や実装と対比した解説が必要では
>>112
unwind不可なのは使いにくい場面が少なからずありそう
今作っているのはdrop使っているから強制abortは問題しかない
117:デフォルトの名無しさん
23/01/29 21:27:11.45 yzACUqHq.net
RustのdropにはRcという具体的な目的がある
Rcが完璧主義ではないのでdropも完璧にする必要を感じない
118:デフォルトの名無しさん
23/01/29 21:32:58.27 ns31yZLJ.net
>>112
>Pythonのsys.exitと同じ感覚でstd::process::exit使うほうがはるかに問題では?
RustではResultをmainまで戻してからprocess::exitする
Pythonは例外という仕組みでランタイムがそれをやってくれる
panicはやってることがにてるからという理由で使うようなものじゃない
119:デフォルトの名無しさん
23/01/29 21:46:05.85 hfoWSJ8/.net
>>115
そうではないよ?例えばrustの標準ライブラリのTcpStreamにはset_read_timeoutでタイムアウトを設定すると、それ設定値以上でpanicを起こす。
これは通信中に非同期制御やスレッド監視などをしないための苦肉の策でResultをmatchするだけという考えから外れて、回復不能としているのだがリードタイムアウトであろうと再試行するようなプログラムではpanicを考慮しなければならない。
一方でTcpStreamの多くはResult<>を返すので、高度なプロトコルを作るような場合、受け取ったデータなどを調べてpanicさせる方法などが公式ドキュメントにも述べられている。
120:デフォルトの名無しさん
23/01/29 21:46:28.34 6XW+IoFB.net
The Bookに書いてるようにpanicを使う対象となるような回復不可能なエラーは常にバグによるもの
Rust groups errors into two major categories: recoverable and unrecoverable errors.
Unrecoverable errors are always symptoms of bugs.
121:デフォルトの名無しさん
23/01/29 21:56:31.01 saQmfbkd.net
>TcpStreamにはset_read_timeoutでタイムアウトを設定すると、それ設定値以上でpanicを起こす。
readで設定したtimeout値を超えたらpanicすると言ってる?
少なくともリファレンスにはResultが返されるとあるんだが
122:デフォルトの名無しさん
23/01/29 21:57:37.90 K3YIwpIF.net
>>113
_exitはexit_groupのラップ関数だよ
123:デフォルトの名無しさん
23/01/29 22:09:10.65 +VDCQEdm.net
言語の理想と実装は違うから食い違いが出ている。現実的には作者がめんどくさくなったり、ライブラリとそれを利用するレイヤーの区別があいまいな場合などに大域脱出とスタック巻き戻しがしたいだけで回復可能な場合にもpanicを投げてしまう実装もありうるのでバグではない。標準ライブラリでさえそうなのだから
124:デフォルトの名無しさん
23/01/29 22:14:20.10 jL8Axswy.net
> 受け取ったデータなどを調べてpanicさせる方法などが公式ドキュメントにも述べられている。
これはpanicを使えということじゃなくサンプルコードとしての簡潔さ優先してるだけ
改善はされてきてるけどunwrapがあちこちにあるのと同じ
箸の上げ下げレベルで手取り足取り教えてもらうことを期待し過ぎじゃないか
125:デフォルトの名無しさん
23/01/29 22:21:53.21 qSgQK/Ke.net
>>118
うん別に良いデザインではないよ、そこは同意する
俺は「同じexitがあるのに」という表現が招きかねない誤解に釘を差しただけです
126:デフォルトの名無しさん
23/01/29 22:33:36.00 +VDCQEdm.net
>>124
もちろんドキュメントで述べられてる通り、Resultが一番の選択肢で回復可能で返せるのにpanicを使うのは愚策でしょう。だから理想はとそういってますよね?
手取り足取り教えてもらうのはどちらなのかというよりも、どうしてもpanicで終了はバグだという理想・意見をとゴリ押ししたいだけに見えます。
これは(=回復可能なのに)panicを使えということじゃなくというのは強く同意ですが、そうなっていないものを使用している現実があるという話でpanicを書いてないことに期待し過ぎじゃないか?ということになります
127:デフォルトの名無しさん
23/01/29 22:38:36.38 yP5ym/xP.net
>>119
Rustでそのような形のpanicの使われ方はしませんしpanicは起きません
タイムアウトもio::Resultでio::Errorが返るだけです
これはC言語で書いてSO_RCVTIMEOでタイムアウト値を設定してreadで-1とerrnoが返る時と全く同じ状況です
言語独自の例外機構を持つ言語は複雑にしてややこしくしているだけなのでその考えをまず捨てるところからスタートしましょう
128:デフォルトの名無しさん
23/01/29 22:44:10.80 yP5ym/xP.net
>>126
今回のケースでも標準ライブラリはpanicを起こしていませんしpanicを起こす仕様はありません
もしpanicが起きたのならばそれはあなたがResultの処理をせずに強引にunwrap()したためであり
あなたのコードがpanicを引き起こしたのです
129:デフォルトの名無しさん
23/01/29 22:49:39.52 ZDOIjMr/.net
The BookにmainまでResultで戻す実践的な設計方法って解説されてる?
機能の説明はあっても実装するうえでどのようにしたらいいのかってところは抜けているような
ググるとstd::num::*を返す例、Stringを返す例、enumを返す例などが出てくるが
どのように使い分ければいいのかって点は不明
このスレ見ていてもこの部分に関する資料を提示している人は見かけないし
>>124
>箸の上げ下げレベルで手取り足取り教えてもらうことを期待し過ぎじゃないか
箸文化圏なら要らないだろうがスプーン・フォーク文化圏なら要るんじゃね
他所と大きく違うのであれば十分な説明を求められるのは当然では
130:デフォルトの名無しさん
23/01/29 22:51:25.05 CZoRokqJ.net
> 例には、不正なデータを渡されたパーサとか、 訪問制限に引っかかったことを示唆するステータスを返す
> HTTPリクエストなどが挙げられます。 このような場合には、呼び出し側が問題の処理方法を決定できる
> ようにResultを返してこの悪い状態を委譲して、 失敗が予想される可能性であることを示唆するべきです。
> panic!を呼び出すことは、 これらのケースでは最善策ではないでしょう。
131:デフォルトの名無しさん
23/01/29 23:19:15.93 B9jwmLl6.net
>>129
mainまでResultで戻すにはResult型を返す関数を書くだけ
何も難しいことはなく複雑なこともなくシンプル
Resultは単なる型の一つでOk値とErr値のEnumに過ぎない
Rust言語はResultに対し例外機構のような特別扱いをしていない
ResultはTryをimplしてるから『?』オペレータを適用できるなどくらいしか他の型との違いはない
したがって新たに勉強すべき点はそこだけだが『?』は使わずとも同じことを記述することができる
132:デフォルトの名無しさん
23/01/29 23:31:48.93 ZDOIjMr/.net
>>131
Result<T, E>のEってなしに出来たっけ?自分が言いたいのはそういう話なんだけど
133:デフォルトの名無しさん
23/01/29 23:45:24.52 B9jwmLl6.net
>>132
特別扱いはないので自由
例えばbool相当としてResult<(),()>型を使ってももちろん機能する
またOption<T>相当としてResult<T,()>型
通常はそれぞれ前者を使って必要なところで初めてResultへ変換が普通
134:デフォルトの名無しさん
23/01/29 23:50:28.46 X9CS5Y/7.net
>>129
> The BookにmainまでResultで戻す実践的な設計方法って解説されてる?
12章はどうだろうか、minigrep を作るところ
135:デフォルトの名無しさん
23/01/29 23:59:14.71 /s+aPXiv.net
>>129
12章に書いてるでしょ
それに一連のレスで書いてる設計指針はRust特有の話じゃないよ
アプリのトップレベルに集約エラーハンドラを用意するのは例外機構のある他の言語でも同じだし
エラー発生時にexitcodeを設定してプロセス終了させるのはUIに相当するレイヤーの仕事だからそこまで戻してハンドリングするのも他の言語でも同じ
pythonだとしてもいろんなレイヤーでsys.exitするのは典型的なダメなやり方
136:デフォルトの名無しさん
23/01/29 23:59:23.38 B9jwmLl6.net
RustはResultを特別視しない
例えばGoのようにRustで(正常値, エラー値)とタプルで返す関数群でプログラミングしても同様に動く
じゃあなぜResultを用いるのか?
・統一した型があった方がいい
・二値ではなく二種のEnumでよい
・便利なメソッド群を標準で用意できる
・標準ライブラリをResultで統一できる
137:デフォルトの名無しさん
23/01/30 00:00:50.47 M6Z3pSeY.net
すまん被ってた
138:デフォルトの名無しさん
23/01/30 00:02:36.60 RUd1b+83.net
>>132
なんでEを無くしたいの?
139:デフォルトの名無しさん
23/01/30 00:09:50.85 Oa/BEQbJ.net
Rust特有のエラーハンドリングの実践的な知識はanyhow/thiserrorの使い方を学ぶといい
それらのcrateを使わず自前でやるとしても何を用意する必要があるのかわかる
140:デフォルトの名無しさん
23/01/30 00:14:09.92 q9Kf6jE6.net
副作用がない関数なら大域脱出を使うべきでないのは分かる
副作用に寛容で大域脱出に不寛容なのは分からん
141:デフォルトの名無しさん
23/01/30 00:19:52.36 1Kzq/YqA.net
>>139
それは初心者には混乱の元
panicとか言ってる初心者たちが最初にすべきことは一つ
「unwrap()を使わずにプログラムを書く」
142:デフォルトの名無しさん
23/01/30 08:11:22.12 sNrNLjHp.net
>>109
>The process::exit function will stop the program immediately and return the number that was passed as the exit status code.
>This is similar to the panic!-based handling we used in Listing 12-8, but we no longer get all the extra output.
>・・・
>Great! This output is much friendlier for our users
exitの使用目的はpanicによる不必要なメッセージの抑制に読めるけど?>>112で触れられている副作用なんか完全スルー
それに明らかに大域脱出を意図した使い方
裏を返せばpanicのメッセージ出力が問題にならないのであればpanicでも構わないとも取れる
143:デフォルトの名無しさん
23/01/30 08:21:18.23 e4IM4WvI.net
もういいよ。お前はずっとpanic使っとけ。
144:デフォルトの名無しさん
23/01/30 08:28:01.11 1Kzq/YqA.net
Rustをきちんと学ぶ気があるならば
まずはpanicもunwrapも使わずにプログラムを自在に書けるようになること
そういう基礎ができていないから勘違いしてpanicにこだわろうとしてしまう
145:デフォルトの名無しさん
23/01/30 08:31:46.93 uyNTp5VX.net
評判の悪いthe book 日本語版にすら使い分けの記述あるのに、それを無視して回復不能なエラー処理以外でpanicを推奨しようとするのは何なのかね。
エラー処理
Rustには例外が存在しません。代わりに、回復可能なエラーにはResult<T, E>値があり、 プログラムが回復不能なエラーに遭遇した時には、実行を中止するpanic!マクロがあります。
146:デフォルトの名無しさん
23/01/30 08:40:51.18 VdE13u+1.net
the bookを一通りきちんと読んだならunwrapは極力使うべきではないものだと理解できるはずなんだけどな
147:デフォルトの名無しさん
23/01/30 11:00:50.02 R3gVBmE3.net
>>138
panicで大域脱出して構わない状況ならmainで必要な情報はreturnするか否かだけ
これはResultが保持しているのでEは不要
148:デフォルトの名無しさん
23/01/30 11:23:44.77 hiS6eSAP.net
>>147
すまんけど全然わからない
TとEの両方がないとResultが存在できないと思うんだが
149:デフォルトの名無しさん
23/01/30 11:26:30.09 q36OfC0i.net
TとEを()にしたら実質ないなので
150:デフォルトの名無しさん
23/01/30 11:36:33.64 2ZbeByHM.net
>>142
ちゃんと読もう
そして全体の文脈を理解しよう
URLリンク(doc.rust-lang.org)
151:デフォルトの名無しさん
23/01/30 11:50:16.61 xWvH9QlK.net
>>149
Eをunit typeにすることをEをなしにすると言ってることは理解したが
>panicで大域脱出して構わない状況ならmainで必要な情報はreturnするか否かだけ
これは全然わからない
大域脱出したいからpanic使いたがってるという動機部分は理解した
152:デフォルトの名無しさん
23/01/30 12:08:29.21 xWvH9QlK.net
exitcodeをちゃんと実装したい時は
process::exitのリファレンスに書いてるように
mainの戻り値にTerminationを実装した型を指定してprocess::exitは使わずmainから戻り値を返す方法が今は推奨
153:デフォルトの名無しさん
23/01/30 12:56:41.01 WhTmZ0y4.net
>>151
処理継続不能なら終了するしかないからね。panicで終了しようが、mainまで戻ってからreturnしようが大差ない
154:デフォルトの名無しさん
23/01/30 19:01:04.95 uxYUj7Ri.net
>>153
いやいや、深いところから脱出するのにResultだと途中の階層すべてで返さないとダメだからコーディングの手間が全然違うだろ
155:デフォルトの名無しさん
23/01/30 19:07:00.52 6jXELBYF.net
>>154
でもアンチpanic君?はその手間を正当化したいっぽいじゃん
156:デフォルトの名無しさん
23/01/30 19:15:25.77 mQYOoXSo.net
日曜プログラマーの作るソフトときちんと作るソフトで基準がズレてる感じ
157:デフォルトの名無しさん
23/01/30 19:23:44.43 mT8msQLw.net
そうやってすぐ人格の問題にする
158:デフォルトの名無しさん
23/01/30 19:39:30.35 dHwZCroo.net
>>154
実際にコーティングしてみれば手間はほぼないと分かる
・返り値型をResult<>で括る
・ライブラリも自作もResult返す関数を上位へスルーするなら「?」を後置
たったこれだけの話
もちろんその場で処理したいResultや情報を増やしたいResultは今回の話以前に元々処理しているはず
回復不能なエラーなんて滅多に起きず
ほとんどはその場か上位関数で何らかの対応処理するエラーなのだから
panicは滅多に必要としない
159:デフォルトの名無しさん
23/01/30 19:54:44.86 kIeP1yzV.net
mainまで戻るってことはmain肥大化と同義。積極的にmainを複雑化させるべきいう主張か
もちろんプログラミングの定石的には1関数にあれもこれも詰め込むのは悪手だよな
panicダメ言っている人は実用的なプログラムを書いたことがあるのだろうか
160:デフォルトの名無しさん
23/01/30 19:54:52.38 uxYUj7Ri.net
>>158
> たったこれだけの話
それを途中の階層全てでやらんとダメだろ
お前こそでかいプログラム組んだことないんじゃね?
そもそも途中の階層は自分が組んでるとは限らんし
161:デフォルトの名無しさん
23/01/30 20:06:49.02 Lj/9/9R5.net
デストラクタ内でexitを使ってはいけない
デストラクタ内で利用可能な関数の中でexitを使ってはいけない
すべての関数はexitを使ってはいけない
こういうことかな
162:デフォルトの名無しさん
23/01/30 20:18:26.31 TH7lLy8N.net
なんかめっちゃ盛り上がってて草
163:デフォルトの名無しさん
23/01/30 20:21:20.63 J7344Opw.net
そもそもPythonのsys.exitだって本当は100点満点の正解コードを目指すなら独自例外作れって話だし
その程度の雑さでいいならRustでも雑にpanicしたっていいじゃない
教科書的な話じゃなく、もっと実利的な問題が何かあるなら教えてくれよ
164:デフォルトの名無しさん
23/01/30 20:22:42.83 1Kzq/YqA.net
>>159
mainまで戻る必要はない
通常は必要なところでエラー処理をする
>>160
エラー処理するところまでの途中のみでResult通過
だから手間なんてない
165:デフォルトの名無しさん
23/01/30 20:23:54.74 i/bC1p00.net
Rustに例外付けなかったの失敗だったな
166:デフォルトの名無しさん
23/01/30 20:27:14.41 9ScRXeeN.net
深い再入階層からジャンプして戻って来れる便利な例外
167:デフォルトの名無しさん
23/01/30 20:31:02.00 Lj/9/9R5.net
>>165
デストラクタ内で例外を投げないのは成功
168:デフォルトの名無しさん
23/01/30 20:33:32.03 uC26F0Aa.net
>>164
> 通常は必要なところでエラー処理をする
それは回復可能なエラーの話だろ
> エラー処理するところまでの途中のみでResult通過
> だから手間なんてない
169:デフォルトの名無しさん
23/01/30 20:50:07.22 1Kzq/YqA.net
>>168
まともなプログラムならば回復可能か否かに関係なく各々のエラー処理をきちんと行う
そのエラー処理を最下位関数内の関数呼び出し毎に行うのではなく中位の関数である程度まとめて行う時にResult返しとそのスルーで集める
このような下位のエラー処理をまとめて行うことはRustに限らずどのプログラミング言語でも同じ
170:デフォルトの名無しさん
23/01/30 20:50:28.09 uC26F0Aa.net
>>164
途中で送信してしまった
> エラー処理するところまでの途中のみでResult通過
途中?
main まで帰る話はもういいのか?w
171:デフォルトの名無しさん
23/01/30 20:51:44.09 uC26F0Aa.net
>>169
回復不可能なのにどんなエラー処理するつもりなんだよw
172:デフォルトの名無しさん
23/01/30 20:58:27.94 1Kzq/YqA.net
>>170
mainまで戻したいかどうかはそのプログラムの自由であってRustとは何ら関係がない
これは例外のある言語でも同じ
例外catchする場所はそのプログラムの自由
173:デフォルトの名無しさん
23/01/30 21:06:59.40 uC26F0Aa.net
回復不可能とか言わなくなってて草
174:デフォルトの名無しさん
23/01/30 21:07:51.47 dHwZCroo.net
元々の回復不能な話はこれだけど
>>47
>> ネットワーク前提にしてる時に、panicになるのはバグではないよ?
おもちゃなプログラムを除くとそういう状態は回復不能と扱わなくて
回復不能はまず滅多に起きることではないよね
そのケースだとネットワークが使えないことを知らせて使えるようになるまでデータを維持して待つ
panicで終わらせてよいのはかなり限定された場合だけとなるよね
175:デフォルトの名無しさん
23/01/30 21:19:29.68 mdZRdLQP.net
回復不能連呼してる人が具体的にどんな状況でのエラーを想定してるのか説明しないのに建設的な議論になるわけがないな
176:デフォルトの名無しさん
23/01/30 21:38:32.03 jfU7NhFo.net
プログラムを使う側からしたら回復可能かどうかなんて些細な問題で処理できる or できないがすべて
そもそも技術的に回復可能であってもそのような実装になっていないプログラムなんて腐るほどある
177:デフォルトの名無しさん
23/01/30 21:42:16.22 1Kzq/YqA.net
>>173
既に書いたように回復可能か否かに関係なくエラー処理は行われる
そして上位でまとまった共通なエラー処理をする時に
途中関数での?オペレータ付加とResult返しのみでRustでは実現できる
例外機構という複雑で非効率な仕組みは必要ないという話が本題
178:デフォルトの名無しさん
23/01/30 22:02:40.15 jfU7NhFo.net
>>174
>そのケースだとネットワークが使えないことを知らせて使えるようになるまでデータを維持して待つ
それは対話式のUIを持っているアプリ限定。CLIのアプリならエラーメッセージを出力して終了するのが一般的
179:デフォルトの名無しさん
23/01/30 22:10:02.38 1Kzq/YqA.net
>>178
その場合でもライブラリの奥底からResult返しの連鎖があり
エラーメッセージを出力する上位まで来てからそのResult処理をする形に変わりなし
個別プログラムの方針とは関係ない共通の話がなされている
180:デフォルトの名無しさん
23/01/30 22:13:28.38 IhW3z+yo.net
コマンドラインオプションでリトライ指定機能追加するときに
なんでもかんでもpanicだと泣きを見るぞ
181:デフォルトの名無しさん
23/01/30 22:19:43.76 uC26F0Aa.net
回復不能って言ってるのにリトライ機能追加とかw
182:デフォルトの名無しさん
23/01/30 22:21:01.07 uC26F0Aa.net
>>177
だから実現はできるけど面倒だって話
183:デフォルトの名無しさん
23/01/30 22:26:05.18 N/PzAAZV.net
fs::read_to_stringでエラーが返されたら回復不能なんでしょw
184:デフォルトの名無しさん
23/01/30 22:38:54.58 IhW3z+yo.net
>>181
接続失敗するだけでpanicにしてるらしいからな
185:デフォルトの名無しさん
23/01/30 22:40:43.76 xNQxd4Kt.net
>>178
curlとかリトライできたりするCLI使ったことないの?
元の質問者が>>39でGUIへの対応方法がわからないと言ってるのも本質的なエラー処理を理解せずpanicしてるからだぞ
186:デフォルトの名無しさん
23/01/30 22:43:08.31 jfU7NhFo.net
>$ cat foo.txt
>cat: foo.txt: そのようなファイルやディレクトリはありません
ここで正しいファイル名を入力しろなどと言いだすCLIアプリは相当レア
187:デフォルトの名無しさん
23/01/30 22:48:41.78 mdZRdLQP.net
>>186
その状況でエラー出して終了させるのは良いとして、まさかpanicさせるなんて言わないよね?
188:デフォルトの名無しさん
23/01/30 22:49:07.10 Rt4q8oMT.net
>>186
$ cat foo.txt bar.txt
とでもやってみろよ
189:デフォルトの名無しさん
23/01/30 22:53:39.09 xlgBAXsb.net
「回復不能」って言葉がよくないんだろうな
エラーの種別についてある程度の前提知識を持ってないとなんでも恣意的に回復不能に分類しちゃう
190:デフォルトの名無しさん
23/01/30 22:59:07.16 nWXKDIRj.net
通りすがりのF#erですが、RustでもRailway指向ってオススメですか?
191:デフォルトの名無しさん
23/01/30 23:25:38.10 nWXKDIRj.net
F#の記事ですが、ResultかpanicするべきかをRailway指向を考えた方が記事にしてます。
URLリンク(fsharpforfunandprofit.com)
ドメインエラーはResult、それ以外はpanicの方が良いって言ってるぽいかな。
192:デフォルトの名無しさん
23/01/30 23:30:11.69 dHwZCroo.net
>>183
その場合でも例えばこのように
Result処理せずにunwrap()してpanicさせたら困ることをpanic派が気付いているかどうかだよね
fn foo(path: impl AsRef<Path>) -> String {
let text = fs::read_to_string(path).unwrap();
// テキスト処理略
}
193:デフォルトの名無しさん
23/01/30 23:56:32.97 WvBRUZ9a.net
>>191
それは例外を使うべきケースと戻り値でエラーの種類を表現すべきケースの区別を例外機構のある言語を前提に語ってるもの
エラーの種別についての前提知識としては役立つがRustのResultとpanicの区別とはまた違う
その人が3種類に分類したエラーのうちPanicsだけがRustで言うところのpanicを使うケースにあたる
194:デフォルトの名無しさん
23/01/30 23:59:11.83 dHwZCroo.net
>>191
その文書のResultやpanicはもちろんRustのそれらとは意味が異なるよ
そして代わりに例外でエラーを返すと書かれていてもRustには例外は無いわけでw
195:デフォルトの名無しさん
23/01/31 00:14:04.93 c7ed+PvI.net
複おじ死んだんじゃなかったの?
いい加減コテつけてくれよな
あと新年の挨拶もまだだろ?まだ1月のうちにやっとけ
196:デフォルトの名無しさん
23/01/31 01:21:48.37 CDUXqGTR.net
>>194
>>193
Rustは例外が無い>try-catchやthrowが無い。
という理解で有ってます?
となると、Resultの守備範囲が広くなりそうですね。
197:デフォルトの名無しさん
23/01/31 04:50:14.13 JnYo5yDi.net
panic・回復不能エラーは滅多にない。
Ruby on Rails でも滅多にない
ファイルが存在しない、数値に変換できないなど、予測可能なエラーは例外。
こういうのは普通に起きるエラー
たぶん、panicを使う香具師は、書き捨てのコードだろ。
リソースの解放・後始末が面倒くさいから
198:デフォルトの名無しさん
23/01/31 06:55:08.97 YNMDboNb.net
>>191
これに尽きるでしょ
・Panics.
These are errors that leave the system in an unknown state, such as unhandleable system errors (e.g. “out of memory”) or errors caused by programmer oversight (e.g. “divide by zero,” “null reference”).
要はpanicはプログラマーにはどうしようもないメモリー不足とかプログラマーの想定外の状態になったときに使うものだよ
他のプログラム言語でもAssertとか使うだろ
199:デフォルトの名無しさん
23/01/31 07:40:09.15 7I30yv0f.net
>>196
そう
Rustはtry throw catchの例外機構を意図的に排除している
例外機構の導入は複雑になるだけだなく効率面での不利や他の機能との相性など様々な問題がある
そのためRustやGoなどのプログラミング言語では例外機構が導入されていない
例外機構のある言語の多くでは例外が素通りする途中の関数でその宣言をしないためコードを見てもその有無が分からない問題もあった
Rustでは戻り型のResultによりそれを扱うことの有無が明確になっている
さらに"?"オペレーターによりResult値が下から上へ素通りすることも明確になっている
つまり簡素化と効率化と可読性の向上全ての両立をRustは実現している
200:デフォルトの名無しさん
23/01/31 07:49:11.46 YNMDboNb.net
>>199
> 例外機構のある言語の多くでは例外が素通りする途中の関数でその宣言をしないためコードを見てもその有無が分からない問題もあった
そりゃ途中の関数にはその例外は関係ないからね
関係ないものを見る必要はない
201:デフォルトの名無しさん
23/01/31 07:53:28.80 7I30yv0f.net
>>200
コードレビューやリファクタリングや移植作業をしたことがあればそれがコードに見えないことは非常に困ると分かる
Rustはそれがはっきりと分かるため可読性が良い
202:デフォルトの名無しさん
23/01/31 07:59:50.04 Tm4r8coX.net
mainからリターンするのであればプログラムの終了に至る条件が増えるほどmainの条件分岐がでかくなる
ってことも理解できない人がpanicダメとか言っているんだね
203:デフォルトの名無しさん
23/01/31 08:27:46.22 cn1TJfcU.net
このスレ見ていると、Rust勉強しているのにコールスタックとかスタックフレームを理解していないやつて意外と多いのが分かるな。
そもそもmainはスタックの根元で、OSとかプログラマーから見てプログラムそのものの代表だろ。
正常なフローならmainで始まってmainで終わるのは定石であって、正常なフローを破壊するpanicは異常事態。
Rustはスタックを重視してResultとか?演算子とか整備しているんだから、わざわざ用途外でpanicを使うのはRustのコンセプトを理解できていない証拠。そんなにスタックフレームのフロー制御が嫌ならRust以外を使ったら?
204:デフォルトの名無しさん
23/01/31 08:35:12.13 7I30yv0f.net
>>202
そもそもpanicするのはメモリ不足くらいしかない
それも最近はtry_reserve()などpanicを避ける対応も増えてきたがまだpush_within_capacity()など安定化していないな
あと固定サイズ内でやりくりするArrayVecのtry_push()を使うこともよくある
205:デフォルトの名無しさん
23/01/31 08:36:17.38 mKWzzzcA.net
例外がないせいで、複数ライブラリ使うとエラー型を合成する必要があってつらいわ
206:デフォルトの名無しさん
23/01/31 08:39:39.26 08CfuspX.net
>>200
入れ子になった関数の途中かどうかなんて関係なく、自身が呼び出した関数から出る例外に無関係な状況など考えにくいんだが
207:デフォルトの名無しさん
23/01/31 08:41:05.82 YNMDboNb.net
>>201
何が困るのか具体的に書いてみ
208:デフォルトの名無しさん
23/01/31 08:42:54.02 YNMDboNb.net
>>206
自分が関与しない例外なんだろ?
その関数にできることなんてないはずだが?
209:デフォルトの名無しさん
23/01/31 08:43:45.56 7I30yv0f.net
>>205
それは"?"オペレータのところでFrom::from(err)変換が自動適用されるので変換をimplしておけばよいだけ
210:デフォルトの名無しさん
23/01/31 08:49:38.58 3fV3plkN.net
panic派の主張は「肥大化するとなんかダサいからエラー処理サボってpanicさせとくわ。コード量は減ってスッキリするから格好いいでしょ」という風にしか聞こえない
どれだけ肥大化しようとも想定が必要なエラー処理を省略しては駄目だろう
211:デフォルトの名無しさん
23/01/31 08:49:41.53 7I30yv0f.net
>>207
例外がそこを通過するのか否かそこを見ただけで分からないからレビューでもリファクタリングでも何でも不便すぎる
一方でRustはそこがはっきりしていて可読性が良い
未処理な事項があって上位へ処理を委託していると明確に分かる
212:デフォルトの名無しさん
23/01/31 08:51:55.45 LXCt1d5H.net
>>205
とりあえず合成したいならanyhow使えばいい
勝手に全部合成されるから使い勝手は例外と変わらんと思うよ
213:デフォルトの名無しさん
23/01/31 09:03:32.22 cRk5v+aU.net
>>212
anyhowで勝手に合成されたエラー型への参照をmain()のifで場合分けしようとしたけど
JSのinstanceof 演算子的な処理のやり方が分からんかったわ
214:デフォルトの名無しさん
23/01/31 09:09:12.08 YNMDboNb.net
>>211
だから不便すぎるとかふわふわした言葉で語るなよw
具体的に何が不便なんだよ
215:デフォルトの名無しさん
23/01/31 09:12:07.56 YNMDboNb.net
>>210
panicはバグとかメモリー不足とかでどうしようない状態になったときに呼び出されるもので通常のエラー処理なんてできないってことぐらい理解しなよ
216:デフォルトの名無しさん
23/01/31 09:18:10.08 7I30yv0f.net
>>213
そういう使い方をしたいならば例えばライブラリA,B,Cに対してMyErrorをEnumでErrorA,ErrorB,ErrorC各収容した方が扱いやすさも効率も良い
そのEnumに格納するだけのコードimpl From<MyError> for ErrorAしておくだけで簡単
217:デフォルトの名無しさん
23/01/31 09:23:20.28 cRk5v+aU.net
>>216
全部自動でやってよ
218:デフォルトの名無しさん
23/01/31 09:28:45.86 7I30yv0f.net
>>214
Rustでは通過する途中の関数においても"?"オペレータの有無で未処理エラーを上位へ委託しているか否かが明白に分かる
だからコードレビューがしやすいし機能追加やリファクタリングする時にも見落としがない
一方で例外機構のある多くの言語では通過する途中の関数を見ても例外が通過するのか否かすら分からない
範囲を大きく広げて探し回らないといけなくなりムダな作業も発生して不便である
219:デフォルトの名無しさん
23/01/31 10:14:19.93 PU9Vswnw.net
>>205
自分のcrate用にエラーenumを定義して下位のエラーはそれにwrapするんだよ
その辺を楽させてくれるのがthiserror
カスタムな例外を定義しなくてもBulit-inの例外を使い回すだけで規模の小さいプログラムなら書ける例外+継承のある言語とは違うところ
Rustの場合はioエラーのみとかじゃなければ常にエラーenumを書くようになる
220:デフォルトの名無しさん
23/01/31 10:15:37.08 YNMDboNb.net
>>218
だから自分が関与しない例外を調べて何をするんだ?
例外使うなら例外安全に作るのは当たり前でその関数が関与したリソースはその関数がきちんと始末することでなんの問題もないでしょ?
221:デフォルトの名無しさん
23/01/31 10:18:35.43 7I30yv0f.net
>>217
そこは自由度があるから自分で必要性に応じて仕様を決めるべき
完全にサボりたいならanyhow等を使えばよいがその代わりにdynによる非効率さと分類の扱いにくさがトレードオフ
222:デフォルトの名無しさん
23/01/31 10:29:38.37 7I30yv0f.net
>>220
中間関数は関与していないのではなくcatchしないことで例外エラーを上位へ移譲している
機能追加やリファクタリングではその処理位置が変わり得るから無関係ではなく把握する必要がある
同じことをRustならば上位への移譲があるか否かが明確に分かるため非常にやりやすい
223:デフォルトの名無しさん
23/01/31 10:37:25.48 YNMDboNb.net
>>222
> 機能追加やリファクタリングではその処理位置が変わり得るから無関係ではなく把握する必要がある
そりゃその関数が関与するような修正するならな、当たり前
でも全ての関数が毎回関与するわけじゃないだろ
なんかダメな理由を必死に探してるとしか思えないけど
224:デフォルトの名無しさん
23/01/31 10:41:06.15 7I30yv0f.net
>>223
コードレビューでも同じ
上位への移譲の有無がはっきり分かるRustは可読性が良い
225:デフォルトの名無しさん
23/01/31 11:26:55.99 5zDIQfkR.net
メモリ不足でパニックとか言っている時点で全く判かっていないの草
メモリのアロケーションに失敗した場合パニックしてもその動作は保証されない
なぜならスタックの巻き戻し中にメモリのアロケーションが試みられないことを保証するのは難しいからだ
そのアロケーションに失敗した場合に二重パニックになる
パニック時にアボートする場合は別だが、その場合はリソースやロックの開放もれが発生する可能性があるね
226:デフォルトの名無しさん
23/01/31 11:52:51.31 df6faTWR.net
>>225
全然ここの話を聞いてなかったけど、C++だとデストラクタは内部で例外を発生しては
ならないと決まっているから、デストラクタ内部ではメモリー不足例外も
発生させてはならない。
227:デフォルトの名無しさん
23/01/31 11:55:03.20 df6faTWR.net
>>226
[補足]
Java などでは、例外を投げるには throw new SomeException(); のようにするが、
C++ では、throw SomeException() のようにする。つまり、前者はヒープから、
後者はスタックから例外オブジェクトを確保する。なので、例外throwそれ自体は
メモリー不足にはならない。
228:デフォルトの名無しさん
23/01/31 11:56:57.46 eIPLUE+9.net
Resultでエラーを表現する一番の目的は
抜け漏れなくエラー対応してることを
シグニチャーを見ただけでわかるようにして
簡単に静的チェックができるようにするため
229:デフォルトの名無しさん
23/01/31 12:41:27.68 YNMDboNb.net
>>224
いらない情報書かれても読みにくいだけ
230:デフォルトの名無しさん
23/01/31 12:44:13.13 +FKSpugG.net
今日もpanic警察が必死です。MISRA-C警察みたい
231:デフォルトの名無しさん
23/01/31 12:45:18.07 YNMDboNb.net
>>225
メモリー不足で動作が保証されないなんて常色だろ
同じくプログラマーの想定外の場合でも動作は保証できないからそういう時は余計なことしないで早期に終了させるしかない
panicってそのためのものだよ
なので個人的にはrustのスタック巻き戻しはやり過ぎだと思ってる
232:デフォルトの名無しさん
23/01/31 12:46:06.11 YNMDboNb.net
>>230
必要ないと思うなら使わなきゃいいのになぜか鬼の敵みたいになってるの草
233:デフォルトの名無しさん
23/01/31 12:47:09.57 oegPHy5Y.net
panic使う人は使っても困らないような
プログラム開発してるだけ
本人が困ってないならそっとしておけ
234:デフォルトの名無しさん
23/01/31 12:51:11.39 CpP2rI02.net
panicを使う理由が対応コード書くのがめんどくさいとか見通しとか回復可能でも呼ぶぜってところからきた話なので
回復不能エラーで呼び出された場合とか当たり前なところ話しても議論にもならんやろ
235:デフォルトの名無しさん
23/01/31 14:46:39.65 YNMDboNb.net
> 本人が困ってないならそっとしておけ
と言いながら構わずに居られない>>233であったw
236:デフォルトの名無しさん
23/01/31 15:00:44.42 hwxs0+db.net
病院行ったほうがいいよ
237:デフォルトの名無しさん
23/01/31 15:03:53.55 ylr44mGO.net
>>233
元からそういう話だぞ。panic原理主義者が発狂しているだけで
238:デフォルトの名無しさん
23/01/31 15:10:39.60 3fV3plkN.net
簡単にpanicされると困るようなプログラム作りたいからこそrust選んだのでは
239:デフォルトの名無しさん
23/01/31 15:39:37.08 CAp90nIJ.net
JavaやC#あたりの経験もなくPythonやJavaScriptしか触ったことがない層がRustをやろうとしてるんだろうな
そうでもないと説明がつかない
240:デフォルトの名無しさん
23/01/31 15:48:38.88 BgaMS/KG.net
言語というよりはエラー種別やドメインエラーをきちんと定義するようなアプリやシステムの開発経験がないからだと思われる
241:デフォルトの名無しさん
23/01/31 15:52:55.96 +s4b9MNJ.net
おじおじしてきたな
242:デフォルトの名無しさん
23/01/31 16:06:06.73 YNMDboNb.net
単発ワラワラw
243:デフォルトの名無しさん
23/01/31 16:33:36.83 hwxs0+db.net
自分以外がすべて同一人物が書いたかのように見えるなら病院に行きなさいって
244:デフォルトの名無しさん
23/01/31 16:45:54.71 VKWM6Cjq.net
複オジ2世レベルやな
立場逆転してるのが感慨深い
245:デフォルトの名無しさん
23/01/31 16:51:02.90 +s4b9MNJ.net
そういえばこんなのもあったな
使ってやってくれ
Rustレスバトル会場
スレリンク(tech板)
246:デフォルトの名無しさん
23/01/31 17:01:16.78 k74gCp3T.net
レスバしたいだけにしか見えねえ
247:デフォルトの名無しさん
23/01/31 17:26:31.56 5mHFhJcn.net
GoとかRustとか例外サポートしなくなった言語、標準でスタックトレースサポートしなくなった辛さにみんなどう対応してるのかね。
エラーメッセージで grep とか、ログからコールスタックを想像とか、かなり辛いんですけど。
248:デフォルトの名無しさん
23/01/31 17:30:47.95 fFj0kljj.net
スタックトレースサポートされてるぞ
だかスタックトレースないとどこでエラーが発生したかわからないような作りは見直すべき
249:デフォルトの名無しさん
23/01/31 18:11:46.10 CpP2rI02.net
古き良きline!マクロ
250:デフォルトの名無しさん
23/01/31 18:25:09.41 Qz5B8C78.net
c++勉強しているけどやっぱりrustっていいんだな
c++の場合どのオーバーロードが足りないかもエラーをチラ見しながら勘で判断するしかない
少なくとも能力の低いワイはそうやって対処している
251:デフォルトの名無しさん
23/01/31 19:05:37.94 Tu8zoz2s.net
例外連呼しているくせに具体的なことを書かない時点でエアプか煽りなんだろうな
例外機構を持つ処理系はエラー処理を局所化できるメリットがある
同様のメリットをRustで得るにはどのような実装が推奨されるんかな?
252:デフォルトの名無しさん
23/01/31 19:31:24.49 p+H/rvZ9.net
そこまで言うなら見せてもらおうか。
スレッド間エラー転送とやらを。
253:デフォルトの名無しさん
23/01/31 19:36:37.66 94wkFUZO.net
URLリンク(i.imgur.com)
254:デフォルトの名無しさん
23/01/31 19:41:28.43 7I30yv0f.net
>>229
Rustの利点に対して「いらない情報」と言い張るのはまるでアンチのように悪意があるなあ
可読性の向上という開発効率でのメリットと実行効率のメリットさらにスレッドやコルーチン実装のタスクからも伝播させることができるRust方式は非常に優れているよ
255:デフォルトの名無しさん
23/01/31 19:47:33.31 YNMDboNb.net
>>254
だからその情報がなぜ必要なのかを書きなよ
毎回可読性の向上って念仏唱えられても困る
256:デフォルトの名無しさん
23/01/31 19:51:16.79 7I30yv0f.net
>>247
Rustは標準でスタックトレースをサポートとしている
何でもいいからコンパイルして実行したことあればRUST_BACKTRACE=1と環境変数をセットすれば出力すると表示されることすら知らないのは不思議
ちなみにstd::backtrace::Backtraceによって自由自在に好きなところでバックトレースをキャプチャすることも出来る
257:デフォルトの名無しさん
23/01/31 19:56:49.64 7I30yv0f.net
>>251
Rustでもエラー処理を上位に委託してエラー処理を一箇所に局所化できる点は全く同じ
いくら初心者でもネット上のBOOKやサンプルや書籍など見てコードを書けばすぐに分かること
258:デフォルトの名無しさん
23/01/31 19:58:31.81 iWzBLVlH.net
>>255
254じゃないけど、メリットは分かりやすいけどなぁ。
関数のインターフェイスに、関数の作用に関する情報がまとまっていたらそりゃ便利だろう。
例外を投げる関数の場合、例外に関する情報は関数のマニュアルを参照するかソースを参照するしかないことがほとんどじゃない?インターフェイスを見ただけで例外を把握できる言語てあったっけ?
259:デフォルトの名無しさん
23/01/31 20:06:28.07 0vRdrBrN.net
ML系の系譜の言語はまあ大体そうなんじゃね
そしてRustでもdyn Errorで返されたら結局同じことやらされる羽目に……
260:デフォルトの名無しさん
23/01/31 20:17:47.02 YNMDboNb.net
>>258
だから例外に関与しないのになぜそんな情報いるんだ?
261:デフォルトの名無しさん
23/01/31 20:25:27.93 QTaicIN8.net
>>260
マジでそれ言ってるの? マジで?
例外を無視しても「例外が投げられる」という作用は消えないよ?
例外が投げられても「俺関与しないから」と言って無視するの?
262:デフォルトの名無しさん
23/01/31 20:27:00.46 1QZESm3t.net
例外に関与しないってどういう意味なんだろう?
ガン無視するって言ってるんだろうか?
263:デフォルトの名無しさん
23/01/31 20:36:05.54 YNMDboNb.net
>>261-262
いちいち曲解するなよ
下位で発生した例外は何もしなければそのまま上位に伝搬するだろ
例外安全に作られてればその関数で確保したリソースはちゃんと解放される
それは下位の例外の種類に依存しない
264:デフォルトの名無しさん
23/01/31 21:10:03.87 QTaicIN8.net
>>263
「上位に伝達する」という意味わかっている?
>258がインターフェイスの話をしているのは理解できている?
関数の呼び出し元からすれば、呼び出し先で投げられているのか、さらにその先で投げられているのか、とか関係なく「関数を使ったら例外を投げられた」だよ。関数のユーザーからすれば「投げる例外くらい明確化するのが常識だろ」と思うよな。
関数が例外を投げるのに、その関数の作者が「例外に関与しないからオレ知らね」とか言って逃げたらブチ切れるわ。そんなんだったら例外全部catchして関数の外に漏らすな、と。
265:デフォルトの名無しさん
23/01/31 21:16:22.90 1QZESm3t.net
>>263
例外安全って意味広すぎて
強い保証したいときとかあるやろ
266:デフォルトの名無しさん
23/01/31 21:28:25.11 Qz/Q1rYV.net
Javaの検査/非検査例外以降の約20年余りの試行錯誤の結果辿り着いた現時点でのベストプラクティスを採用したのがRustやSwiftのエラー処理モデル
C → Java → C# → Go →Swift/Rust
267:デフォルトの名無しさん
23/01/31 21:35:24.95 Mxurit6u.net
>>263
そうやって
ヌルポで落ちるプログラムを量産したんだよね
268:デフォルトの名無しさん
23/01/31 21:42:42.48 QTaicIN8.net
まぁ、Result使うとしてもtry catch finallyブロックみたいなフローが欲しいというのはわからんでもない。
関数から抜ける時にResultを漏らさず処理したいというのはたまにあるし。
269:デフォルトの名無しさん
23/01/31 21:48:12.48 jD2BQUnk.net
>>263
catchとかしないの?回復処理したり付加情報付きの例外投げ直したり
そのためにはcatchすべき例外が上がってくるかどうか知らないといけないんだけど
270:デフォルトの名無しさん
23/01/31 22:04:35.47 WaCEL3Yw.net
この件でプログラミング言語が最低限サポートして欲しい点2つ
ある関数(ライブラリ)を使おうとした時に
①その関数やその子孫からエラーや例外が上がってくるのか、それとも全て処理済なのか?
これが奥深く辿らなくても局所的に把握できること
ドキュメントベースはそのミスや見落としが生じるため不可
②エラーや例外が下から上がってくる関数を用いた時に、
その処理をせずに続行してしまうコードを書いてしまったら、実行前に言語システムにより防げること
例えばRustならば①は返値がResult型かどうかですぐに把握できる
②は型システムによりRustコンパイラが型不一致や未処理放置Resultの存在を伝えてくれる
Rustは現在ベストなプログラミング言語と言い切っても過言ではない
271:デフォルトの名無しさん
23/01/31 22:16:44.29 Mxurit6u.net
>>270
高い信頼性が要求されないプログラムなら
例外と集約エラーハンドラさえあればいいんだから
Rust的なモデルが最適化どうかは要件次第だよ
結局はトレードオフ
272:デフォルトの名無しさん
23/01/31 22:19:53.43 Mxurit6u.net
>>268
今でもResultを漏らさず処理できると思うんだけど
できないのってどういう状況?
273:デフォルトの名無しさん
23/01/31 22:45:41.29 WaCEL3Yw.net
>>271
趣味のおもちゃプログラムでなければ信頼性は必須だよね
それだけでなく>>270の最低限の2点はプログラマーにとっても必要なこと
①を満たせない言語では無駄に調べまくらなければいけない
②を満たせない言語では無駄に実行時デバッグを強いられる
トレードオフと言われても信頼性と開発効率を両方落とすのは割に合わない
274:デフォルトの名無しさん
23/01/31 23:47:23.84 ovWek0QN.net
使いたい関数だけじゃなくて、その関数が使ってる関数、更にその関数が、、、って調べていかないといけないのが無駄にコスト高になるんだよね。
275:デフォルトの名無しさん
23/01/31 23:54:22.59 hwxs0+db.net
>>274
使いたい関数のシグニチャ見れば分かることだろ?????
276:デフォルトの名無しさん
23/02/01 00:33:02.66 CK4ZTpUy.net
やっぱ複オジは成長しねーな
2世と同類だわ
277:デフォルトの名無しさん
23/02/01 03:40:06.80 RyGmTTdX.net
>>275
それが正しいか信頼できんだろ
278:デフォルトの名無しさん
23/02/01 06:17:22.82 5NtLPUR3.net
>>275
Rustならば使う関数のシグネチャを見ればResultが返ることで>>270の①を知ることができるけど
例外機構の言語の多くはシグネチャには情報がないため完全に信頼できるドキュメントでもない限り下流の関数全調査になるかな
②の処理忘れ防止機能も含めてRustが最も整備されている言語という感じ
279:デフォルトの名無しさん
23/02/01 07:12:22.77 Hf88nfPH.net
>>264
だから上がってくる例外を処理する必要があるならその時に調べればいいでしょ?
例えばprintfみたいな関数作ってる時に下位のputsみたいな関数がI/Oエラーで例外上げてくるだろうけどそれはそのまま上位にあげるだけだろ
いちいち意識する必要はない
>>265
強い保証の意味がよくわからんが自前でキャッチして処理すれば良くね?
>>269
全ての関数で回復処理が必要なわけじゃないし情報を付加するだけなら例外の種類を問わずにキャッチしてスローすればいいでしょ
すべての階層で事細かく例外をキャッチしてスローし直すなんてことは普通やらないよ
280:デフォルトの名無しさん
23/02/01 07:21:02.47 Hf88nfPH.net
>>270
言いたいことはわかるけどそれを実現する手間が掛かりすぎると思う
そもそも例外を上げるかどうかだけを見たいならnoexceptを真面目に実装すればいいだけだし
281:デフォルトの名無しさん
23/02/01 08:02:53.27 5NtLPUR3.net
>>280
それを実現する手間が掛かりすぎる、という視点がむしろ既に間違えているのかもね
従来の例外の枠組みを持たずにRustは>>270の二点をシンプルで効率よく実現してしまった
つまり従来の例外の枠組みよりも利便性と信頼性の高い新たな枠組みが実用的だと示されたのだから
従来の例外の枠組みを捨てるべき時が訪れたと解釈する方が正しいのかもしれない
282:デフォルトの名無しさん
23/02/01 08:17:31.54 rokbXrwB.net
>>272
あ、漏らさず処理はできるな。ごめん。
言いたいのは「似たようなエラーをまとめておいて、修正も一括で行う」のイメージだった。
例えば「関数内で細切れでファイルに書き込んでいるとき、どこかで書き込みエラーが出たらロールバックしてログを取って再書き込みする」とか。
>>279
やっぱり全然理解できていないな。
その「printfみたいな関数」を使う「上位」のプログラマーはどうすんだよ。「例外に関与しないからオレ知らね」か?
そんなんだったら例外全部catchして関数の外に漏らすな。
283:デフォルトの名無しさん
23/02/01 08:17:38.20 Hf88nfPH.net
>>281
> 従来の例外の枠組みを持たずにRustは>>270の二点をシンプルで効率よく実現してしまった
シンプルだけど生産効率は良くないよね?
って言ってるんだけど...
284:デフォルトの名無しさん
23/02/01 08:20:02.84 Hf88nfPH.net
>>282
上位で処理する必要があるならその時に調べればいいだろ
途中の関数で逐一調べる必要はない
そもそも最下位の関数に新しいエラーが定義されたらrust使いは全部調べ直すのか?
285:デフォルトの名無しさん
23/02/01 08:25:05.41 ATJMUMOg.net
>>279
その調べるかどうかをどう判断するかって話なんだが…
putsがI/Oエラーを上げてくるって知ってるから無視して上に上げるって判断ができるわけ
じゃあライブラリXの関数Yは無視すべきなのかそうでないのか?ってこと
286:デフォルトの名無しさん
23/02/01 08:27:52.62 rokbXrwB.net
>>284
どうやって調べるのか、具体的に考えた?
インターフェイスしか提供されていなくて、ソースコードの無いライブラリとかでどうやって調べるの?
エスパーか神様でもなければ不可能だね。
287:デフォルトの名無しさん
23/02/01 08:30:01.09 5NtLPUR3.net
>>283
むしろ>>270の二点をサポートしているRustは開発効率が高いでしょう
それらをサポート出来ていない従来のプログラミング言語は開発効率も信頼性も低いわけです
開発効率と実行効率と信頼性の高さを両立させたRustの地位は揺るぎないと思われます
288:デフォルトの名無しさん
23/02/01 08:37:05.02 rokbXrwB.net
ダックタイプ系の開発効率を求めるならRustは選択すべきじゃないよね。メモリの取り扱い見ればRustは「作法を強制する言語」だということは明らか。
そういうのはPythonとかRubyとかスクリプト言語があるんだからそっちを選ぶべき。
289:デフォルトの名無しさん
23/02/01 08:41:21.89 wznv5J1H.net
>> 279
> 強い保証の意味がよくわからんが自前でキャッチして処理すれば良くね?
他は既に突っ込まれてるから言わんが
例外に関するプログラミングしてたらすぐにわかる概念だからググれ
つうか例外安全って言葉使うなら知っとけ
290:デフォルトの名無しさん
23/02/01 08:54:40.02 Hf88nfPH.net
>>285
例えばprintfみたいな関数で下位の例外を処理するのか?
処理するとして何をやるんだ?
って話
考え方が逆なの、自分に関与しない例外は触らない
>>286
ライブラリならドキュメントに書いてあるでしょ
>>287
また呪文唱え始めたのかw
せめてこれに答えてよ
> そもそも最下位の関数に新しいエラーが定義されたらrust使いは全部調べ直すのか?
291:デフォルトの名無しさん
23/02/01 08:55:45.56 Hf88nfPH.net
>>289
> 例外に関するプログラミングしてたらすぐにわかる概念だからググれ
また無能のググれかよw
答えられないなら無駄に絡んでくるなよ
292:デフォルトの名無しさん
23/02/01 08:58:06.40 ATJMUMOg.net
>>290
別に調べ直す必要はないよ
下位にエラーが追加されても直接呼び出す関数のシグネチャが変わらないなら対応不要、変わったら対応するってだけ
結局呼び出す関数のResult型が対応すべきもののすべてなんだからそれ以外見る必要がない
293:デフォルトの名無しさん
23/02/01 09:02:33.17 JRuvbVor.net
>>288
そういうCPUもメモリも浪費するエコでない言語との比較はほとんど意味がないんじゃないかな
GC言語であってもそこそこ速いJavaやGoくらいの立ち位置の言語ならば比較の意味があるとしても
294:デフォルトの名無しさん
23/02/01 09:20:03.74 JRuvbVor.net
>>290
> そもそも最下位の関数に新しいエラーが定義されたらrust使いは全部調べ直すのか?
Rustでそんなことをする必要がないよ
元々他のエラーも返す関数だったならば返り値型が元々Result型だから枠組みは変化なし
新たにエラーを返すように返り値型が変わったならばコンパイルエラーで気付く
295:デフォルトの名無しさん
23/02/01 09:26:13.19 ypE1x0h9.net
fishシェルをRustで書き直すことが(ほぼ)決まったよ
URLリンク(github.com)
C++ と CMakeをかなり腐してるけど意外に荒れてない
ちなみに提案者は開発リーダーなのでほぼ決まりでしょう
リンクされてる移行プランは他のプロジェクトでも参考になりそう
296:デフォルトの名無しさん
23/02/01 12:36:36.73 o2DBVRIO.net
>>292,294
> 元々他のエラーも返す関数だったならば返り値型が元々Result型だから枠組みは変化なし
なら、その新しいエラー(例えばディスクフルを検出してたが今回ディスクオフラインなんてエラーが追加された)の処理が抜けてないことはどうやってわかるんだ?
実行時にしかわからないなら例外と変わらん
むしろ途中の伝搬コードをいちいち書くのが面倒なだけだろ
297:デフォルトの名無しさん
23/02/01 12:42:13.45 BH4poKX+.net
Elixir にも、try/rescue の例外があるけど、あまり使わない。
throw/catch, raise でも、例外の発生場所を関数の外側から内側へ移すだけ
try do
%{a: a} = map
{:ok, a}
rescue
MatchError -> {:error, ":a が無い"}
end
とは書かずに、パターンマッチで書くのがElixir流
case map do
%{a: a} -> {:ok, a}
_ -> {:error, ":a が無い"}
end
298:297
23/02/01 12:45:24.97 BH4poKX+.net
>>297
修正。内側・外側が逆だった
>throw/catch, raise でも、例外の発生場所を関数の外側から内側へ移すだけ
throw/catch, raise でも、例外の発生場所を関数の内側から外側へ移すだけ