Rust part19at TECH
Rust part19 - 暇つぶし2ch200:デフォルトの名無しさん
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 でも、例外の発生場所を関数の内側から外側へ移すだけ

299:デフォルトの名無しさん
23/02/01 14:01:39.16 TUW+NsdV.net
>>296
それはResult<T,E>のEで返されるエラーenumのvariantが増えるだけ
んでvariantが増えればEをハンドルしてるところでexhaustiveに処理してなければコンパイルエラー

300:デフォルトの名無しさん
23/02/01 14:08:16.76 w5pt5x/h.net
>>282
>言いたいのは「似たようなエラーをまとめておいて、修正も一括で行う」のイメージだった。
これはResultのコレクションを返せばいい
例外のある言語でもこのケースは例外じゃなくエラー情報を貯めたオブジェクトを戻り値で返してエラーがあったかどうかをチェックして分岐するコードを書く
それと似たようなもの
>例えば「関数内で細切れでファイルに書き込んでいるとき、どこかで書き込みエラーが出たらロールバックしてログを取って再書き込みする」とか。
ロールバックする系の処理ならエラーを貯めずにエラーが一つ出た時点で中断するように作ったほうがいい

301:デフォルトの名無しさん
23/02/01 15:31:55.23 4CkJdapD.net
脳死でdyn Error突っ込んでるやつです

302:デフォルトの名無しさん
23/02/01 15:34:50.34 ypE1x0h9.net
dyn Errorで受け取った後の活用法が分からん

303:デフォルトの名無しさん
23/02/01 17:49:22.59 HDxpsRMp.net
dyn Errorでできるのは
・print!とかwrite!でログ出力する
(ErrorトレイトにDebugとDisplayが内包されてるからちゃんと実装されてれば何か教えてくれる)
・source()で内部のdyn Errorを掘り起こす
(エラーの原因のエラーがあれば一緒にログ出力できる)
くらいだからログ出力以上の活用がしたいならそのためのError型を使わないといけない

304:デフォルトの名無しさん
23/02/01 18:15:38.74 pHJayYFi.net
>>302
具体的なエラーの型で分岐させたいならダウンキャストが必要(The Bookにも書いてたはず)
エラーenumを定義してwrapしたものに変換(map_err)しておけばダウンキャストは不要
anyhowに組み合わせてthiserrorの#[from]や#[error(transparent)]を使うと楽にwrapできる
anyhow/thiserrorのやってることに最初から自力で辿り着くのは大変だから先に使ってみて必要な要素を学んだ方が早いよ

305:デフォルトの名無しさん
23/02/01 19:06:46.56 JRuvbVor.net
>>303
dynはErrorに限らず自由に元へ戻せるよ
例えばstd::io::Errorを含むdyn Errorが返ってきた時
if let Some(io_err) = dyn_err.downcast_ref::<io::Error>() {
 match io_err.kind() {
  io::ErrorKind::NotFound => {
このように細かいエラーハンドリングが可能
>>304
順序が逆だよ
まずは標準ライブラリ内で上記のようにdyn Errorを使ったり
あるいはdynを使わずにimpl From<MyError> for io::ErrorでMyErrorのEnumに格納する「?」時の自動変換を書いたり
それぞれ簡単で単純なパターンなのだから標準ライブラリで基礎を身に着けた上で自作や外部のライブラリを選ぶのがお勧め

306:デフォルトの名無しさん
23/02/01 19:07:10.38 sE34HuOS.net
>>290
例外をサポートしているような言語なら、投げる例外を関数のインターフェイスとしてドキュメントに記載する。
Rustなら>>292

>考え方が逆なの、自分に関与しない例外は触らない
>290が>285 >286を理解できない無能だということは理解できた。
c++とかでライブラリ関数からドキュメントに無い例外を投げられた経験が無いんだろうな。おめでたい。

307:デフォルトの名無しさん
23/02/01 19:18:58.38 RjOpz7Dl.net
単発無能認定おじさん

308:デフォルトの名無しさん
23/02/01 19:27:56.01 JRuvbVor.net
>> ライブラリならドキュメントに書いてあるでしょ
ドキュメントは言語システムの一部ではないため
ミスで現実のコードとドキュメントが食い違っていることもあれば
ドキュメントは正しくても利用者が見落としてしまうこともある
大規模な開発になればなるほどミスや見落としが紛れ込むことは避けられない
特にエラー処理が済んでいるか未だなのかは致命的になりかねない
一方でRustは言語システムの中で下位関数からエラーが上がってくるか処理済か分かる
さらにResultが未処理のままだとRustコンパイラが指摘してくれる
言語システムとして少なくともこれらの機能を持つ言語へと今後は移行していくべき流れ

309:デフォルトの名無しさん
23/02/01 21:57:57.91 qgBIsers.net
>>305
>それぞれ簡単で単純なパターンなのだから
実装の簡単さやパターンの単純さが問題じゃないんだよ
Rustのエラー処理に必要な「それぞれ簡単で単純なパターン」を網羅的に知識として仕入れてRustのエラー処理はこうやってやるものだと自信を持って言えるようになるまでの学習効率の問題
anyhow/thiserrorはそのパターンを楽に使えるよう作られてるから「ああRustのエラー処理ってこうやればいいんだな」ってのが標準ライブラリ前提で学ぶより断然早く理解できる

310:デフォルトの名無しさん
23/02/01 22:05:04.46 JRuvbVor.net
>>309
dynの取り扱いと「?」オペレータによる自動変換はRustの基本事項で必須の知識
もちろん標準ライブラリの中で完結して使えるしシンプル仕組みなのですぐ使えるようになる
この基本を習得せずに外部ライブラリへ行くことを勧めるのは基本知識を欠いた人を生み出してしまう愚かな行為

311:デフォルトの名無しさん
23/02/01 22:25:39.32 JqtaL/Do.net
>>310
もしかしてパターンってdyn Errorと?オペレータ使った自動変換の話だけなの?
それだけじゃRustで現実的にどうエラー処理を実装すべきかThe Book読み終えたくらいの人にはわかんないと思うよ

312:デフォルトの名無しさん
23/02/01 22:59:41.62 JRuvbVor.net
>>311
エラー処理パターンは様々な方針があり
その前提知識としての共通の必須事項として今回のスレの流れで話が出て来ていたdynの取り扱いと?での自動変換の話を書いた
例えばあなたが出したanyhowはdyn Errorを扱う外部ライブラリの一種
anyhow::Errorから具体的な型を取り出すためには>>305で書いたdynの取り扱い知識が必須
この知識を知らないと細かいエラー分類が出来ずにエラー表示のみしか出来ない人になってしまう
もう一つあなたが出したthiserrorも?での自動変換を用いる外部ライブラリ(というかマクロ)の一種
>>305で示したFrom::from()による自動変換の基礎知識を欠いたままでは仕組みすら分からず魔法のように外部ライブラリを使うダメな人になってしまう
応用が効かないだけでなく利用していて何か問題にハマった時に基本知識がないと解決することもできない

313:デフォルトの名無しさん
23/02/02 00:32:13.04 y8eaHXgz.net
>>312
設計やプラクティスとしてのパターンのことを言ってたんだが君は言語機能のことをパターンと呼んでるみたいで噛み合ってないよね
dyn Errorや?オペレータ使ってinto経由で変換されるような基本的な機能面の知識はThe Bookにも書かれてるレベルだし多少分からなくてもリファレンス読めばいいだけの話
でもそれだけの知識でRust初心者がエラー周りの実践的な設計をできるようにはならないでしょ

314:デフォルトの名無しさん
23/02/02 00:53:57.92 tzaW+blt.net
anyhow/thiserrorは最近出てきた新興ライブラリ
当然それまでは誰も使っていなかったわけで初心者がいきなり必須なものでもない
初心者にとっては複雑で機能過多で理解しにくいのでまずは標準ライブラリから始めたほうが良いかな

315:デフォルトの名無しさん
23/02/02 01:38:05.78 JL6WsU2I.net
対象年齢付きのおもちゃか何か?w
自分だけ勝手に縛ってろw

316:デフォルトの名無しさん
23/02/02 03:39:28.87 S9qGtTXE.net
Rustは「教官付き教習車」だよ。
cとかと違ってアホが膝を撃ち抜く自由は許さない。
それが嫌ならRust止めれば?

317:デフォルトの名無しさん
23/02/02 07:11:05.90 02L2EQ2o.net
Rustはコンパイラの防波堤の中で安全な自由があるけどそれはともかく
クセの強いanyhowをRustの基本より先に初心者に教えるのはあかんよ
たとえば、他人も使うライブラリ作成ではanyhowの使用を避ける、といった当たり前のことも
エラーに関する基本を知らないと陥ってしまう

318:デフォルトの名無しさん
23/02/02 07:31:00.57 c3pJ+FwE.net
>>316
rustの免許とりたいんですがおすすめの教習所はありますか?w

319:デフォルトの名無しさん
23/02/02 07:34:23.41 /W20jYzd.net
anyhowはもはや標準ライブラリでしょ

320:デフォルトの名無しさん
23/02/02 07:55:32.16 Cx26n0QZ.net
>>317
あれはクセというよりanyhowの致命的な欠陥だ
分かってる人は配慮して閉じた環境だけで使うけど稀に公開ライブラリにanyhow使っちゃう無知な人もいる
基礎知識はホント一番大事

321:デフォルトの名無しさん
23/02/02 08:05:47.28 VrfwqxiC.net
>>318
コンパイラ(教官)はひとつしか無いから選択肢は無いよ。

322:デフォルトの名無しさん
23/02/02 08:14:13.18 eMZEpDOV.net
コードを貼るわけでも実装例を示すわけでもない時点でシッタカだろ

323:デフォルトの名無しさん
23/02/02 09:11:33.63 ICVq01Bq.net
anyhow勧めてる人自身があんまり理解してないんだと思う

324:デフォルトの名無しさん
23/02/02 12:40:03.75 8vdGQp5R.net
複オジが使ったことないだけだろ
>>312も今調べてきました感満載じゃん
デファクトスタンダードになってるライブラリまで排除したらrustでは何もできんぞ

325:デフォルトの名無しさん
23/02/02 12:47:49.51 YyXCj6j+.net
オライリー本にも実戦ではanyhowとthiserrorを使えと書いてる

326:デフォルトの名無しさん
23/02/02 12:59:53.51 c3pJ+FwE.net
>>321
うまいこといいますね。お見事!

327:デフォルトの名無しさん
23/02/02 13:20:28.44 C8PK02xw.net
禁忌事項はライブラリを作って提供する時にanyhowを使ってしまうことだけだから
そこはanyhowを使わずにthiserrorを使えばヨシ

328:デフォルトの名無しさん
23/02/02 15:47:50.42 HD9HoUeH.net
別にanyhowをthiserrorに差し替えるのも大した手間じゃないしな
ライブラリで使っちゃってるなら変更PRでも出してやれば良い

329:デフォルトの名無しさん
23/02/02 23:07:11.98 3wRXRcn7.net
>>325
anyhowとthiserrorを使うなと言ってる人は誰もいなくて
・まず先にstd::error::Errorを覚えよう
・次に?変換とdynダウンキャストを覚えよう
・そしてanyhowとthiserrorへ進もう
という話でしょ
そうすればanyhowをライブラリで使うべきでない理由もわかるでしょうし

330:デフォルトの名無しさん
23/02/02 23:14:43.66 3quZbai0.net
Rustの世界でダウンキャストってなんかキモいな

331:デフォルトの名無しさん
23/02/02 23:37:26.35 wswA48V7.net
むしろRust基盤の一つ
downcastはエラー処理に限らずdyn Traitを元の型に戻すために必須
anyhowでも元のエラー型に戻すために必須

332:デフォルトの名無しさん
23/02/02 23:53:43.61 86yN0Q3V.net
ダウンキャストのソース見てみたら
やっぱりunsafeのかたまりだった

333:デフォルトの名無しさん
23/02/02 23:53:52.64 QEJ+oT50.net
ダウンキャストを知らないと
>>303のようにdyn Errorで出来ることはログ出力だけと思いこんでしまう

334:デフォルトの名無しさん
23/02/02 23:59:01.23 Cx26n0QZ.net
>>332
当たり前
Rustの標準ライブラリはunsafeだらけ
原理的にunsafeは避けられないからそれを安全なインターフェイスとして公開するのがRustの標準ライブラリ

335:デフォルトの名無しさん
23/02/03 00:57:17.44 teLYlQt8.net
dynを元の型に戻すという発想に違和感(気持ち悪さ)を感じる人もいると思う
元の型に戻すつもりならそもそもdynにしないというか
ダウンキャストは戻すべき型(の変更)を全部把握できる閉じた状況じゃないと使いにくい

336:デフォルトの名無しさん
23/02/03 01:37:41.39 VgIBWdEw.net
>>335
anyhowを使うのはそういう全部把握できる閉じた状況で
独自エラー型を用意するのが面倒な時に使うからダウンキャストが理に適っている
嫌ならanyhow使わずにthiserrorを使えばよい

337:デフォルトの名無しさん
23/02/03 07:58:09.95 +r7mcEDE.net
>>335
型を全て把握しておく必要はない
例えばエラー処理で大半はエラー表示のみだが一部だけ特別な処理をしたいとすると
その処理したいエラー型のみダウンキャストして使えばいい
ちなみにダウンキャストは内部で定数のu64で表現される型番号をu64比較するだけなのでコストがかかるものではない

338:デフォルトの名無しさん
23/02/03 08:54:57.66 Vma9tJMI.net
ダウンキャストの扱いかどうか知らんが、パターンマッチングも総和型から個別型ヘのキャストみたいなもんだろ。

339:デフォルトの名無しさん
23/02/03 09:11:06.24 +r7mcEDE.net
もしdyn使わずに自作Enum収容エラー型を定義して使っても
Enumタグ比較で分岐することになるから状況は似たようなもの

340:デフォルトの名無しさん
23/02/03 09:18:29.47 H94wvEsC.net
std::any::Any.downcast_ref() を使わずにanyhow独自に実装してるね

341:デフォルトの名無しさん
23/02/03 09:36:29.67 e19a6Rdo.net
初めて間もないけど
println!("{}", a);
とか手が攣って辛い
tabでもprintlnまでしかでないしコピペでもしてるの?

342:デフォルトの名無しさん
23/02/03 09:43:50.06 90dUFc67.net
downcastすればいいだけだからdyn Error返してもデメリットは無いってのなら
ライブラリでanyhowを使うのも大した問題じゃないって結論になるん?

343:デフォルトの名無しさん
23/02/03 10:26:25.61 5QmoSp+n.net
>>342
anyhowの問題点はそこではない
anyhowは最も重要なことを実装していない(不可能)という欠点があるため

344:デフォルトの名無しさん
23/02/03 10:31:15.17 Vma9tJMI.net
>>343
anyhowの問題点なんて一般的じゃないんだから、曖昧に言わずに具体的に説明しなよ。

345:デフォルトの名無しさん
23/02/03 10:48:35.31 yQvnFmTM.net
予言しよう
ググれば分かるんだから書かないとか言って絶対に具体的な説明はしないやつだよ

346:デフォルトの名無しさん
23/02/03 12:00:34.82 7ZLHWUFf.net
俺はなんも知らんから頭の片隅に覚えておくくらいにしとくわ
使うときに調べる

347:デフォルトの名無しさん
23/02/03 12:23:43.68 dwx7vokg.net
>>345
検索しても出てこなかったよ。

348:デフォルトの名無しさん
23/02/03 12:37:16.79 tbHpIbwJ.net
Rustでエラー型はstd::error::Errorトレイトを実装するのが共通のお約束だけど
anyhow::Errorは諸事情あって実装されていないんよ
std::error::Errorトレイト実装を前提として扱っているところへライブラリがanyhow::Errorを返しちゃうと困っちゃう
ライブラリを作るときはthiserrorでエラー型を作ればstd::error::Errorトレイトを自動で実装してくれるから大丈夫だよ
もちろんthiserror使わずに自分で実装してもいいよ

349:デフォルトの名無しさん
23/02/03 15:29:10.83 Vma9tJMI.net
>>348
「このライブラリはanyhow対応必須です。anyhow対応しないと使えません」
ならOKかね。

350:デフォルトの名無しさん
23/02/03 18:59:27.03 NDb3ccU3.net
Box<dyn Error>もErrorトレイト実装してないよ(コンフリクトで実装できない)
その点はdyn Errorで返してもanyhowで返しても大差ない
libraryのpublicなAPIでtype erasedなエラーを返したいときは
Errorを実装した独自のエラー型を用意するのが普通
anyhowで返してる有名ライブラリもあるけどね
ライブラリでanyhow使ったらダメなんてことは特にないんだけど
Readme読めばすぐわかるように基本的にはアプリケーション用
なぜ同じ作者のエラー系のライブラリがanyhowとthiserrorと2つあるんだろうか?
と疑問に持つだけでも初心者はstdベースで学習するよりも1歩先に進めてる

351:デフォルトの名無しさん
23/02/04 00:38:01.54 5aCWsuCk.net
ダウンキャストは静的チェックできず変更に弱いからホイホイ使うものじゃないよ

352:デフォルトの名無しさん
23/02/04 07:20:32.73 eqpqpGi8.net
>>351
ダウンキャストは静的に型を指定して
Some()で静的な型で値が返ってきて
その値の使用も静的に型チェックされる
「マッチングが動的ではないか?」については
Enumで複数の型を収容した場合と全く同じ
どちらの場合もマッチングは動的に行われるが静的に型チェックされる
どちらも静的に型を抽象化した定数の整数値との比較によるマッチングとなる点も同じ

353:デフォルトの名無しさん
23/02/04 09:46:17.84 4OrKEijd.net
ばかばかc

354:デフォルトの名無しさん
23/02/04 09:59:08.11 wSUDs8sY.net
Rustのdynとそのdowncastは安全性と最小限のコストを両立させており安心して使える
引数などでimpl Traitが使える場合はimplが有利なケースもあるが
返値などでdyn Traitしか使えない場合もあり適材適所で使い分け

355:デフォルトの名無しさん
23/02/04 10:30:58.71 yB06Lfm4.net
>>352
よくわかってないものを人に勧めちゃダメだよ

356:デフォルトの名無しさん
23/02/04 12:22:28.04 eqpqpGi8.net
久々に荒らし発生かな

357:デフォルトの名無しさん
23/02/04 12:44:13.93 vEFKnpWX.net
ダウンキャストの安全性みたいなのは downcast_ref 使ってりゃ議論の余地はないと思うけど網羅性は限界があるわね。
ライブラリはやっぱエラー型を明示すべき。

358:デフォルトの名無しさん
23/02/04 13:10:09.04 QerlffZr.net
match式によるパターンマッチでは、そのマッチアームによる条件網羅性がコンパイル時に検証される。
enumとmatch式は相性抜群だよな。
URLリンク(doc.rust-jp.rs)

359:デフォルトの名無しさん
23/02/04 13:39:49.84 A1ugYU/e.net
エラー処理で網羅性は関係ないだろ
std::io::Errorのenum ErrorKindからしてnon_exaustive指定だぞ
match式で網羅性はチェックされない
特別な処理が必要なエラーだけ処理対応して残りはエラー表示が普通だ

360:デフォルトの名無しさん
23/02/04 13:52:58.01 RtFCJdnN.net
エラー処理で重要なことは
・エラーが発生しているにも関わらずそのまま通常処理を進めないこと
・エラー表示以外の対応を必要とするエラーの場合にその対応をすること
・それ以外のエラーはエラー表示などをすること
enumタグレベルの網羅性を求められることはないな

361:デフォルトの名無しさん
23/02/04 14:46:52.23 7PnUG+Eh.net
元々の話はdyn Errorかanyhowか、だったような気がするけど、
anyhowはdyn Errorの自作ラッピングみたいなもので、
とちらを使ってもダウンキャストしなきゃいけない点も網羅性がない点も同じだよね。
そしてそれらをアプリ側で使ってる限り困ることもない。

362:デフォルトの名無しさん
23/02/04 17:06:34.73 1vu2ZDPp.net
そもそもがダックタイピングとか向いてる言語じゃない。
フロントでこの言語使おうとするとかただのバカでしかないわ。

363:デフォルトの名無しさん
23/02/04 17:36:37.29 roDrLtFP.net
唐突にフロントとかダックタイピングとかどうした?
しかもその二つも関連性がない

364:デフォルトの名無しさん
23/02/04 18:06:27.05 uIknpDmG.net
上位レイヤーも含めてエラーの内容によって分岐したいならdyn Errorはやめたほうがいい

365:デフォルトの名無しさん
23/02/04 18:34:38.01 srvPtSil.net
分岐にenumのタグを使うかErrorの型名を使うかの違いでしょ
enumを使うと一貫性を担保しやすいから保守性が向上するし
dyn Errorを使うとenumの定義を省略できるからコードを減らせる
自分は(分岐するなら)enum派だけど何を重視するかで結論が変わりそう
ただ「やることが一緒だからどっちも同じ」と考えはいただけない

366:デフォルトの名無しさん
23/02/04 18:40:15.09 3y1LLse5.net
>>364
dyn Errorをやめるべき理由がない
まさかと思うが代わりにanyhow使えとか言い出すんじゃないんだろうな?

367:デフォルトの名無しさん
23/02/04 19:00:20.00 eqpqpGi8.net
dyn Errorもダウンキャストも使用して全く問題ないよ
有名どころでも普通に使われている
例えばreqwestはdyn Errorを使っていてdowncast_ref()してエラー処理している
cargoはanyhowを使っていてdowncast_ref()してエラー処理している
使うのをやめたほうがいいと主張している人は一種の宗教にすぎないことに気付こう

368:デフォルトの名無しさん
23/02/04 22:40:19.42 JjHQagj1.net
勘違いしてる内容が同じだから
自演しまくっても同一人物なの丸分かりだね
ダウンキャストオジ==複オジ

369:デフォルトの名無しさん
23/02/05 02:20:20.64 VCqNNrEk.net
無敵やな
もちろんいい意味で

370:デフォルトの名無しさん
23/02/05 02:25:01.54 a/eU++XN.net
一年ぐらい前にanyhowを標準化する、みたいな話なかったっけ?

371:デフォルトの名無しさん
23/02/05 02:59:04.83 26rYdUrG.net
anyhowはダウンキャストするしかないクソ

372:デフォルトの名無しさん
23/02/05 06:00:11.27 TqN0qcyT.net
オライリーの本って出てから1年経つけどさあ
これの電子版って、セールになったりする機会ってあるもんなの?

373:デフォルトの名無しさん
23/02/05 06:31:13.67 qzS4+JVd.net
ダウンキャストを毛嫌いしてる人の心理を知りたい

374:◆???
23/02/05 12:21:29.64 gCGZ2Fk+q BE:2843802656-2BP(0)
std::mem::transmute

375:デフォルトの名無しさん
23/02/05 12:11:30.30 vL4nY6Md.net
>>359-360
おまえはまるで何もわかってないのな
エラーハンドリングの基礎すらおさえてないじゃん
無知なのはいいが自信満々で嘘を書きまくるのはやめろ

376:デフォルトの名無しさん
23/02/05 12:37:36.14 yQ5U4c14.net
作るシステムの性質や分野ごとで許されるエラーハンドリングは別物だからね。
ミッションクリティカルだけが正解ってわけでもないのよ。

377:デフォルトの名無しさん
23/02/05 14:02:09.96 dIeXO9aa.net
>>376
何がまちがってるかさえも分からないようならThe Bookを一から読み直して出直してこい

378:デフォルトの名無しさん
23/02/05 14:22:39.74 Ib1Yzzhk.net
たまに出てくる「間違っている」「勘違いしてる」「嘘を書くな」の人
今までも文句をつけるだけで正確を書いたことがないから信頼できないのよね

379:デフォルトの名無しさん
23/02/05 14:23:18.13 8OOQa3AE.net
どっちも自分の脳内シチュでしか語ってないからふわっふわで論破出来るわけもなし
自分の主張が通る具体例上げるといいよ

380:デフォルトの名無しさん
23/02/05 14:35:53.55 LY0V54Tb.net
「カッコウのアルゴリズムさえまともに実装できてないからクソ遅いんだよな」
みたいに適当なワード混ぜて意味不明なこと言いつつ同意してる風を装うと「そうなんだよ!」とか勝手に乗っかってきて自爆するから面白いぞ

381:デフォルトの名無しさん
23/02/05 15:42:56.66 XUJKjP/6.net
>>378
それは信頼以前に、相手にしなくていい外野
>>380
すごく目に見えるわその展開w

382:デフォルトの名無しさん
23/02/05 15:53:21.98 ANWYibFj.net
>>373
台所まで行けば箸(enum)があるのに手元のフォークで焼きそばを食べてる感じ
食べてるのがパスタ(Python)なら平気なんだけど

383:デフォルトの名無しさん
23/02/05 16:01:07.42 3wawDpMD.net
>>382
微妙にわかりにくい例えで草
でも複オジに比べると1000倍マシ

384:デフォルトの名無しさん
23/02/05 16:04:59.96 0ZBI/vwq.net
>>378
信頼するかどうかはあなた次第
>>359-360が嘘だらけだということが分からない人は基礎がなってないから勉強やり直すかパスタにするか

385:デフォルトの名無しさん
23/02/05 17:40:20.51 X5wQdMGf.net
網羅性が必要ないならResult使う必要もRustを使う必要もないわな

386:デフォルトの名無しさん
23/02/05 18:32:46.51 rtbv+KUs.net
>>382
凄い納得
enum使わずにanyhow使うような連中はPythonでも使っていろ
anyhowなんてものがあるから勘違いが起こる

387:デフォルトの名無しさん
23/02/05 20:10:29.95 QsKcw+fO.net
cargo crateのコード見てみた
anyhowを使ってエラーを上へ上げていく
enumを使っておらずエラーの網羅性はない
downcast_refを使ってエラー分岐している

388:デフォルトの名無しさん
23/02/05 20:38:51.85 1L9Nz43N.net
エラーなんて作成時点で未知のものが後から増えることもザラだし
何なら抽象レイヤー以下の実装の差し替え(ストレージのネットワーク化とか)で
動的に増えたりすることもあるんだから、網羅性とかすぐ成り立たなくなる。
可能なところで逃すものじゃないけど、こだわるものでもない。

389:デフォルトの名無しさん
23/02/05 21:15:55.10 yQ5U4c14.net
cargo みたいに手元や CI で実行するツールのエラー処理なんてその程度で十分ってこった。
もちろん、網羅が必要な領域のコードじゃそんなエラーハンドリングのやりかたじゃあ駄目だろうよ。

390:デフォルトの名無しさん
23/02/05 21:31:31.79 kVul7/Hf.net
多数の下部ライブラリから色んなエラーが上がってくるreqwestはそれらをdyn std::error::Errorへ入れているね
そしてdowncast_refで必要な分岐をして処理しているね
エラー処理はこれで十分でしょ
網羅しなくても残りは最終的にちゃんとエラー表示されるのだから

391:デフォルトの名無しさん
23/02/05 22:59:47.83 cfofmdL5.net
エラー処理で必須な網羅性とはenumの網羅性とは異なる
いつどこでどんなエラーが発生しても必ず処理されることがエラー処理の網羅性
つまりエラー処理されないまま通常処理に進まないことでありRustではResultの利用によりそれが保証されている
したがってdyn Errorを使って一部をダウンキャストによりエラー処理し残りをエラー表示処理でも網羅性を満たしている

392:デフォルトの名無しさん
23/02/05 23:51:35.27 BjcIBdbF.net
opaqueなerror typeを使うメリットは何なのか?デメリットは何なのか?
少なくともreqwestの開発者はそのトレードオフを検討した上で判断を下している
メリットもデメリットも理解できてないやつが珍説唱えても虚しいだけだぞ

393:デフォルトの名無しさん
23/02/05 23:54:47.07 arvSMdBl.net
>>391
おまえはエクストリームな言い訳並べ立てる前にnon_exhaustiveの意味から調べろな

394:デフォルトの名無しさん
23/02/05 23:58:58.86 QsKcw+fO.net
>>391
やっぱりそれでいいのか
Rustの標準IOライブラリはenumを使っているけどnon_exhaustive指定がしてありenumの網羅性チェックをむしろ使えないようにしてる

395:デフォルトの名無しさん
23/02/06 00:09:01.18 ZXNgtENY.net
>>391
一般的なエラー処理の網羅性はその解釈だな
Rustでは型システムと返り型Result及びResult放置をコンパイラが警告してくれるため必ず網羅される仕組み

396:デフォルトの名無しさん
23/02/06 01:23:09.90 Kt6dB8yb.net
>>394
non_exhaustive指定があると
なぜenumの網羅性チェックが使えないの?

397:デフォルトの名無しさん
23/02/06 06:52:59.94 OJBoAdFu.net
逆だよ
網羅性の扱いを禁止するために意図的にnon_exhaustive指定されている
そのようなエラーの種類には網羅性は必要がないだけでなく
今後もしエラーの種類が増えた場合に全網羅列挙して使用している既存のコードがエラーとなってしまう
そのためこういう時は不要である網羅性の扱いを禁止して全列挙コードを書かせないことで
今後エラーの種類が増えても既存の利用コードに影響を与えずに済む仕組み

398:デフォルトの名無しさん
23/02/06 12:30:43.08 wr+6RDlb.net
>>397
自信満々に間違った情報を中身のない文章で膨らませてもっともらしく見せようとするところがChatGPTそっくりww

399:デフォルトの名無しさん
23/02/06 12:48:04.84 /nZ/7Knj.net
昔ながらの例外論争見てるみたいだ
全部取ればいいいや個別だ

400:デフォルトの名無しさん
23/02/06 14:14:21.50 C/yeK4bx.net
>>397で合っているけど補足すれば
全網羅列挙コードを書いてもコンパイラがそれを許さずエラーとなる
全網羅列挙しなくていいから必ず全マッチの _ => アームをコンパイラが要求してくる
つまりコンパイラによるエラーの網羅性チェックは不可能

401:デフォルトの名無しさん
23/02/06 21:51:09.46 MJNtWgHJ.net
そもそもRust以前に他のプログラミング言語でもそのようなエラーの種類の網羅が行なわれたことはない
IOエラーだけでも何十種類もあり列挙するだけでも大変で意味のない作業
エラー処理で必要とされる網羅性とはエラーの種類を全て列挙することではなく
>>391の説明が正しい
RustでResultを使えば保証される

402:デフォルトの名無しさん
23/02/06 21:59:33.19 T23InEdz.net
自分の書いたレスを正しい正しいと
一人で連呼してて虚しくならないのかな

403:デフォルトの名無しさん
23/02/06 22:26:04.02 7y0OcpN0.net
エラー処理の網羅性という話は元々
関数からエラー値が返って来る可能性があるのに見落として処理せずに続行しちゃったり
あるいは例外が返って来る可能性があるのに見落として処理しないままでいたり
そういう見落としがよく起きていたから
いつどこでどんなエラー(or例外)が起きても処理漏れがないようにプログラミングしましょうという話
もちろんRustではResultで返せばコンパイル時点でエラーや警告が出るためエラー処理の網羅性は満たされます
Resultを返していればdyn Errorやanyhowを使っていてももちろん大丈夫
そしてエラー処理の分岐にそれらのダウンキャストを使うのも何ら問題なし

404:デフォルトの名無しさん
23/02/07 02:02:21.05 smEuFI89.net
anyhow使ってて困ったことないので、これからもanyhow使いますね

405:デフォルトの名無しさん
23/02/07 02:09:15.61 2blGAjQQ.net
enumで網羅派の完全敗北だな
anyhowやdyn Errorでdowncast_ref分岐して何ら困らない

406:デフォルトの名無しさん
23/02/07 02:13:05.33 fMWAnbF1.net
anyhowは邪道だろ

407:デフォルトの名無しさん
23/02/07 10:30:33.69 jDwZWgRX.net
下手に分かったふりせず疑問をぶつけるパニック君のようなレスはスレにとっては有益
逆に知ったかぶりして嘘を撒き散らす某オジのレスは害しかない
一緒に仕事してても伸びるのは断然前者のタイプ
後者は多少知識があってもチームの足を引っ張る老害タイプ

408:デフォルトの名無しさん
23/02/07 11:56:13.05 Yu/MJcLX.net
>>407
知ったかぶりもだけど
ご飯論法的に毎回論点を捻じ曲げてくるのが悪質
スルー推奨

409:デフォルトの名無しさん
23/02/07 12:39:13.84 GmLWJf7C.net
どの言語を使っていようがテスト設計とエラー処理設計は初心者と脱初心者を見分けるリトマス試験紙
チュートリアルやリファレンス読むだけでは身につかない

410:デフォルトの名無しさん
23/02/07 13:41:38.43 vPUoP0i3.net
そう、IT土方必修

411:デフォルトの名無しさん
23/02/07 20:09:18.77 RZZKb5qe.net
>>410
こういうバカが一人でも入ってくると現場は苦労するわな

412:デフォルトの名無しさん
23/02/07 22:03:06.31 u8XyY9YO.net
今回のケースはRustのエラー処理を他の言語(C#あたり)の例外処理に寄せようとしてる感じ
「特定の例外クラスをcatchしたい」→「dyn Errorで投げてダウンキャストで分岐すればいい」みたいな
anyhowはそういう人のためにあるのかもしれない
オブジェクト指向言語専攻の人はRustのtraitを基底クラスの代わりに使いがちだよね
is-a継承はRustだとenumで表現できる場合が多いんだけど切り替えが難しいのかも

413:デフォルトの名無しさん
23/02/07 22:27:27.04 23ICgzsB.net
単純にエラーの種類を列挙する意味がないときに使うだけやで

414:デフォルトの名無しさん
23/02/07 23:09:28.73 u8XyY9YO.net
それならいいんだけど型キャストしてまで分岐するとか言ってる人がいたから
自分で分岐する範囲くらいは自分で列挙しとけって話

415:デフォルトの名無しさん
23/02/07 23:53:31.04 23ICgzsB.net
下層から上がってくる99種類のエラーはログ吐かせるだけで、特別な処理したいエラーはひとつしかないのにいちいちenumに詰め直したりせんわな

416:デフォルトの名無しさん
23/02/08 00:04:28.76 mV68xos2.net

自分で分岐してエラー処理すんなら区別すべきエラーを決めるのは自分なのでanyhowやdyn Errorでダウンキャストしても問題ない
外から呼び出されるコードなら区別して処理するエラーを決めるのは呼び出し側なので区別できるようにenumで書く

417:デフォルトの名無しさん
23/02/08 00:35:28.79 ydIblX/+.net
すまんが、これってなんでダメなの?
ブロックの最後に式を書いてるのに、なんでreturnって書かないとリターンしないの???
そもそもエラーの内容に書いてあるmismatched typesって、一体何と何のタイプがミスマッチなんなんだ・・・・
URLリンク(play.rust-lang.org)
エロい人教えて!!!

418:デフォルトの名無しさん
23/02/08 01:51:02.48 U3de6tMw.net
>>417
else句が無いのでifの条件式がfalseの場合はif-expressionは()になるけど
ifの条件式がtrueの場合はif-expressionがi32になるのでミスマッチ

419:デフォルトの名無しさん
23/02/08 01:59:22.59 W8WwzKcT.net
>>415
ログを吐かせるだけでもエラーによってログの吐き方を変えたいこともよくある話なのでケースバイケース
99種類を2種類に詰め直して片方をerased typeにしたりする

420:デフォルトの名無しさん
23/02/08 07:28:48.49 2c2bFNHO.net
上位の関数でもかなり多数のケースに分けてエラー処理する必要な場合だと
個別にenumにエラー型を収容する方が有利なケースもある
もちろんその場合でもanyhowやdyn Errorに収容してダウンキャストしてもよい
enum matchとダウンキャストの実行時コストはほぼ同じで優劣はなく視認性も変わらない
enumを使うとコードが増える問題はあるがあとは好みの問題

421:デフォルトの名無しさん
23/02/08 10:45:01.05 ENpYrX9l.net
ダウンキャストは下位モジュールに不必要に依存することになるので選択の余地があるなら基本的には使うべきではない
自crateで定義したエラー型にダウンキャストするくらいならエラーを定義するついでにenum書いとけばいいだけ
他crateで定義したエラー型にダウンキャストしてるとバージョンアップ時にサイレントにキャストが失敗して動作が変わる
あくまで非常口であって使わざるをえないときはマイナス面を理解した上で注意深く使うもの

422:デフォルトの名無しさん
23/02/08 10:52:13.58 fJPPomwd.net
UnknownErrorにわざわざ詰め直したログ吐くしかできない99種類あったエラーと1種類の自クレートのMyErrorをenumで2つ列挙して分岐するのと
MyErrorも含めて100種全部dynで上げてMyErrorだけダウンキャストすることの間に大した違いはない

423:デフォルトの名無しさん
23/02/08 12:29:34.73 /lg+THEr.net
アプリケーション開発とライブラリ開発の2つの視点があって、それぞれで戦略が違うというのが大元にあるからそこは理解してもらわないとね。

424:デフォルトの名無しさん
23/02/08 12:40:19.14 TursxKDi.net
ライブラリでdyn Error使うと本体の型がpubじゃないときにめんどくさそう

425:デフォルトの名無しさん
23/02/08 12:45:18.46 QfEWSkwW.net
両者で大きく異なるよね
ただし既出のcargoやreqwestなど違いに関わらずダウンキャストを使っているコードも多いから
どっちだと良くてどっちだとダメというものでもない気がする

426:デフォルトの名無しさん
23/02/08 12:48:39.58 QfEWSkwW.net
424は422へのレスね
>>424
そこはenum作って収容しようがdyn Errorに収容しようが関係なくpubじゃない型はどうにもならないような

427:デフォルトの名無しさん
23/02/08 13:05:56.18 B9DUhvwN.net
>>422
どういう種類の変更に対してコードのどの部分に手を入れる必要が出てくるのかを考えてみるといいよ

428:デフォルトの名無しさん
23/02/08 13:15:25.12 Fgr/3fzw.net
求められてもない具体性のない中身のない全く役に立たないアドバイスは有害でしかない

429:デフォルトの名無しさん
23/02/08 13:35:42.99 DnIJ53A+.net
現実にdowncast_ref()が使われているアプリやライブラリが多数あり
それらが問題になったことはないのだから
downcast_ref()を嫌っている人は思い込みで好き嫌いに過ぎないことを理解しようぜ
enumを作っても下位のエラー型を突っ込むだけでは何も変わらない

430:デフォルトの名無しさん
23/02/08 14:12:14.99 SqObziFu.net
ここまで具体的なコード例なし

431:デフォルトの名無しさん
23/02/08 14:40:13.85 J3DHyZUt.net
前提条件付けて場合分けして考えろ
てかこんなことでスレの半分近くも消費すんな

432:デフォルトの名無しさん
23/02/08 16:15:41.93 ydIblX/+.net
>>418
そうだったのか!returnを書いたら通るのも、そうするとどちらも戻り値が()同士で統一されるってことか!
ありがとう!全然わかんなかったぜ!

433:デフォルトの名無しさん
23/02/08 16:16:54.39 VvFQM19K.net
>>418
>>417では無いが、そういう意味だったのか
単に厳し目にチェックしているからだと思っていた

434:デフォルトの名無しさん
23/02/08 17:13:58.11 e6ub/0SO.net
たぶんだけど「Rustでは値を返すのにreturnを省略できる」と誤解してるんじゃないかな
その誤解のためreturn bのreturnを省略してしまったと思われる
正しくは「Rustでは最後の値が返り値となる(のでreturnが不要)(だが使ってもよい)」
と「途中で返したい時はreturnを使う」
だから今回の例だと
if文の中では『途中だから』return bとbにreturnが必須
あるいは関数の最後をif-else式にしてしまえば『最後となるから』bにreturnは不要

435:デフォルトの名無しさん
23/02/08 17:28:24.72 e6ub/0SO.net
ちょっと誤解があるから追加
最後をif-else式にすれば全体に式returnのreturnが不要になる
そしてif-else式の中はreturnは不要というか付けない
そこにreturnを付けるとif-else式ではなぬif-else文になる

436:デフォルトの名無しさん
23/02/08 18:12:57.92 uJD0QVJP.net
文章を難読化しすぎやろw

437:デフォルトの名無しさん
23/02/08 18:22:49.80 KYgqZ0R0.net
面倒だから戻るところはすべてreturn書いてる

438:デフォルトの名無しさん
23/02/08 20:39:29.96 EOwXjjdD.net
return式の型は厳密には!なんだけど……
まあ後で知ればいいか

439:デフォルトの名無しさん
23/02/08 20:50:18.79 e6ub/0SO.net
そのおかげでif式でreturnしつつelseで値を与えたりできるね

440:デフォルトの名無しさん
23/02/09 11:57:24.62 w55r8U1C.net
早期returnはバグにつながるから禁止が常識

441:デフォルトの名無しさん
23/02/09 12:14:59.38 bVNNfLSa.net
>>440
昔はそう言われたけど今はそんなカス風習廃れたしRustに持ち込まないでほしい。

442:デフォルトの名無しさん
23/02/09 12:15:50.03 UhaInviD.net
早期returnは(>>440みたいなアホが使うと)バグにつながるから禁止が常識

443:デフォルトの名無しさん
23/02/09 12:41:16.10 S7fEOBGh.net
わざわざ早期リターンのために?演算子なんて用意してるRustで早期リターン禁止とな?!

444:デフォルトの名無しさん
23/02/09 12:43:02.37 EmRyIpwb.net
スルースキル皆無か

445:デフォルトの名無しさん
23/02/09 13:10:12.86 wPt4Q+MY.net
なんで昔は早期returnがバグにつながると考えられてたの?
どう考えても早期returnしない方がバグにつながりやすいと思うんだが

446:デフォルトの名無しさん
23/02/09 14:20:08.85 QqGr+Vdk.net
もっと昔にgotoの使いすぎで制御構造がぐちゃぐちゃになったことへの反動で
複雑な制御構造は使わないようにしよう、という流れだったかと

447:デフォルトの名無しさん
23/02/09 14:55:47.47 UhaInviD.net
>>445
C言語時代の話な
例えばこういうパターンでメモリーリークしたりするバグがたくさんあった

f(...){
p = malloc(...);
...
if(...) return;
...
free(p);
}

448:デフォルトの名無しさん
23/02/09 15:21:57.59 9WtqRr2n.net
そのあたりも自動メモリ開放のRustなら大丈夫だね
if文で早期return/continue/breakしないと、どんどんifネストが深くなっていくのでそれを避けたい

449:デフォルトの名無しさん
23/02/09 15:37:28.09 Ktnp537B.net
>>447
リソース確保・解放するレイヤーとそれを使って処理を行うレイヤーを分ければよくない?
f(...){
p = malloc(...);
g(p, …);
free(p);
}
g(…) {
...
if(...) return;
...
}
ifのネストが浅くなっても逆に関数のネストが深くなりすぎて読みにくくなる側面があるということなのかな?

450:デフォルトの名無しさん
23/02/09 15:51:48.67 oQtbOpVY.net
>>449
分けましょうってルール化したくらいで完璧に守られるなら誰も苦労しないんだよな…
そのうち処理レイヤー側でmallocするやつが出てくるやつ

451:デフォルトの名無しさん
23/02/09 15:59:20.91 Ieoj7bJI.net
RAII無しでの話なんかRustに関係無いだろ。

452:デフォルトの名無しさん
23/02/09 16:04:18.76 1694Wm1I.net
ifがネスとしていたりした場合に、returnみたいにif-expressionの方に結果を返したい時ってどうすればいいの?

453:デフォルトの名無しさん
23/02/09 16:22:54.26 eQhq+cyr.net
>>450
早期returnはやめましょうルールは完璧に守られる保証があると?

454:デフォルトの名無しさん
23/02/09 16:24:27.43 g7YoScpU.net
>>452
擬似コードでいいのでイメージを書いてくれ
でないと言いたいことが分からない

455:デフォルトの名無しさん
23/02/09 16:25:56.79 VnFQyKoO.net
>>452
最近入ったラベル付きブロックでbreak

URLリンク(rust-lang.github.io)

456:デフォルトの名無しさん
23/02/09 16:36:32.32 8ktpZl0b.net
言語仕様的に可能でも規則で縛ることで安全を担保しようという方法は
いずれ失敗するからそういう要素は必ず言語側の仕様で保証すべき、というのがRustの思想なんだから
「あれは危険だから駄目、コーディング規則で縛る」という発想自体が間違ってる

457:デフォルトの名無しさん
23/02/09 16:43:33.27 UhaInviD.net
>>449
リソースが1つだけならいいかも知れないけど複数リソースが絡んでたりすると色々ややこしいコードになっちゃう
>>453
コードレビュー時に return 検索したら

458:デフォルトの名無しさん
23/02/09 16:44:45.59 UhaInviD.net
>>451
>>440 に言ってくれ

459:デフォルトの名無しさん
23/02/09 16:48:27.59 jx1YaHu3.net
>>457
なるほど
そういう方法だけに頼ってるなら早期returnのほうが見つけやすいわな

460:デフォルトの名無しさん
23/02/09 16:49:18.29 9WtqRr2n.net
こういうやつ?
let result = 'found: {
 for i in 0..100 {
  if f(i) {
   break 'found Some(i);
  }
 }
 None
};

461:デフォルトの名無しさん
23/02/09 17:15:30.09 1694Wm1I.net
>>454-455
>>460
やりたかったのこれだ、せんきゅー!

462:デフォルトの名無しさん
23/02/09 17:27:44.71 vSSl5weC.net
最近はCでもcleanup属性というのが使えるんだな

463:はちみつ餃子
23/02/09 17:43:07.29 zt0qN6wf.net
>>445
構造化が重要視された時代がある。
順次・反復・分岐によって処理の流れを構築するという点から見ると
早期リターンは流れをすっとばして大ジャンプしてることになるので
コードを追うのを難しくすると考えられていた。
「出入口はひとつずつ」は基本思想だったんだよ。
構造化が不十分だった時代にまず構造化することが大事だったという話。
今では構造化が当たり前になったから次の段階として順次・反復・分岐という構造だけでは
上手く扱いづらい部分をどうやるのがいいのかという模索が続いてるわけ。

464:デフォルトの名無しさん
23/02/09 18:03:17.12 9WtqRr2n.net
戻るgotoは結局なんらかのループを表しているので
Rustならラベル付loopに指定continueで表せる
進むgotoは無制限ではなくラベル指定breakの大域脱出型に制限される
という認識で合ってる?

465:デフォルトの名無しさん
23/02/09 18:18:38.11 xZSrodqJ.net
>>455
なんか微妙な機能だな
関数化して早期returnさせる手間が嫌ということなんだろうけどそれなら||や&&オペレータをOptionやResult用に上書きできるようにした方がずっと使いやすい
tryブロックとの非対称性も気になる

466:デフォルトの名無しさん
23/02/09 18:30:28.03 9WtqRr2n.net
>>465
今までに既にあった機能のラベル付loop式のラベル指定breakという使われ方のうち
ループしない使われ方が多かったため事実上のシンタックスシュガーが導入されただけだよ
だから微妙な機能が追加されたという見方は正しくない

467:デフォルトの名無しさん
23/02/09 18:30:33.67 QonGkYb5.net
>>465
ほとんどの場合はこんなん使う前にその部分を関数に切り出すことを考えるべきというのはめちゃくちゃ言われてる
awaitとかResultとかライフタイムとかいろいろ絡んできたときに再利用もされない数行の処理のために長々と型を書かなくても済むのがユースケースのひとつと思われる

468:デフォルトの名無しさん
23/02/09 18:46:56.04 RAzSpXh0.net
>>466
シンタックスシュガーも機能やろがい
公式にもlanguage featureと書いてるぞい

469:デフォルトの名無しさん
23/02/09 18:50:34.43 hFEBZw9k.net
どうせなら仮変数みたいな変数割当機能も用意して、末尾最適化再帰風ループもできるようにならないかね。

470:デフォルトの名無しさん
23/02/09 18:53:10.62 9WtqRr2n.net
>>468
既に昔から存在していたloop式を
loopと書かなくてもよくなっただけだよ
今までは皆はloop式の最後をbreakすることでloopさせずにこの同じ機能を使っていた
今回でloopを省けるようになったため最後のbreakが不要とだけにすぎない
今さら文句をつけるのが不思議

471:デフォルトの名無しさん
23/02/09 19:02:26.27 o9a7e9s5.net
早期returnってファウラーのガード節の話じゃないん?
あの使い方する限り安全安心可読性改良にしかならないよな?

472:デフォルトの名無しさん
23/02/09 19:04:01.20 EmRyIpwb.net
>>471
ファウラーじゃなくてリーダブルコード?

473:デフォルトの名無しさん
23/02/09 19:05:50.10 o9a7e9s5.net
リーダブルコードは忘れたけど
part of martinfowler.com
URLリンク(refactoring.com)

474:デフォルトの名無しさん
23/02/09 19:15:02.58 9WtqRr2n.net
if letでネストが深くならないように早期return等しようとすると無駄コードが膨らんでいた問題も
同時に導入されたlet elseによって解決されたね

475:デフォルトの名無しさん
23/02/09 19:24:14.80 EmRyIpwb.net
>>473
そうこれ、というか第1版からあるならファウラーが先なのね
失礼した

476:デフォルトの名無しさん
23/02/09 19:31:22.46 Kxe1JjXm.net
「ルールだからダメ(思考停止)」な人って結構いるよね

477:デフォルトの名無しさん
23/02/09 19:40:55.17 rpwFU8e5.net
ルールの背景を考えずに破ろうとするやつも多いけどな。
守破離は基本だろ。ブルースリーのパンチキックの逸話でもいいけど。

478:デフォルトの名無しさん
23/02/09 19:47:18.19 Kxe1JjXm.net
>>477
合理的なロジックがないという点で同類じゃね
「ルールだから問題ない(思考停止)」で他人に迷惑をかけるのも同じ
そして多くの場合無責任までセットだ

479:デフォルトの名無しさん
23/02/09 19:54:21.56 bVNNfLSa.net
そもそも失敗できなくするのがここ10年ぐらいのトレンドだろ。
だから静的型やRustが支持されるわけで。

480:デフォルトの名無しさん
23/02/09 20:07:33.02 rpwFU8e5.net
>>478
ルールについては「決定と実行の分離」という重要な側面があるよ。
頭のいい奴がルールを作れば、アホがルール通りに実行しても被害は少ない。アホがルールを破るよりよほどマシ。

481:デフォルトの名無しさん
23/02/09 20:20:31.75 9WtqRr2n.net
Rustの制御構文としては
昨年末の2つの追加で
従来は不便で需要が多かった形が無事に解決したから一段落かな

482:デフォルトの名無しさん
23/02/09 22:05:48.35 nhsBAAgr.net
>>465
わかる
旧世代言語のニオイがする

483:デフォルトの名無しさん
23/02/09 22:51:32.40 YnVskMRN.net
こういうの書くやつが出るから
基本は使わないほうがよさそうだな
URLリンク(github.com)

484:デフォルトの名無しさん
23/02/09 23:06:57.24 QonGkYb5.net

何らかの目的で大域脱出を用意すると必ず妙ちくりんな悪用を考える奴が出てくるんだよな

485:はちみつ餃子 ◆8X2XSCHEME
23/02/09 23:22:20.06 zt0qN6wf.net
そういえばコンテナのイテレーションの順序が未規定なときに
順序に依存したコードを書かないように乱数でわざとデタラメな順序にしたら
乱数生成器として使うやつが出てきたって話があったな。

どんな機能も下手に使ったら無茶苦茶にしうるってのはもうどうしようもなくない?

486:デフォルトの名無しさん
23/02/09 23:42:25.26 iUuqvbE0.net
>>56のが実現したらRFCの例は||で代替可
let result = (first_container.iter().find(|&&v| v > 0)
|| second_container.iter().find(|&&v| v < 0))
.unwrap_or(&0);

labelやbreakの手続き的なやり方よりこっちの方が汎用性も高いしrustの目指すべき方向に合ってると思う

487:デフォルトの名無しさん
23/02/10 01:49:50.47 JoKDyp+E.net
メソッド抽出は嫌
クロージャの即時実行も嫌
ラベル付きbreakならOK!
って感覚が俺には理解できんが
ニーズがあるならいいんじゃね

488:デフォルトの名無しさん
23/02/10 02:22:12.82 KiCBMwJT.net
>>487
関数切り出しやIIFEだと式の値はResult型になるようなところで、
ラベル付きブロックだとエラーまわりは親の関数に完全に任せて該当の式の値を生で返せる

489:デフォルトの名無しさん
23/02/10 02:35:52.13 8y57Q10t.net
ラベルでジャンプより、関数の入れ子の方が分かりやすくない?

490:デフォルトの名無しさん
23/02/10 03:36:08.11 eoPLVAGF.net
>>488
?オペレータ使えばいいだけなんだが?
逆にエラーまわりだけ親関数に任せるとかヤバくね?

491:デフォルトの名無しさん
23/02/10 06:59:25.26 Fpp4vOr0.net
>>489
ラベルでジャンプしていない
loop式の構文のloop抜きと動作も概念も全く同じだから
今回Rustはたまたま同じ構文を採用しただけ
例えば>>460の例は
ラベルを用いない別の新たな構文{{…}}を導入すればこうなる
let result = {{
 for i in 0..100 {
  if f(i) {
   return Some(i);
  }
 }
 None
}};
動作も意味も全く同じであり
ラベルにジャンプしていないことが理解できるだろう

492:デフォルトの名無しさん
23/02/10 07:32:00.75 Fpp4vOr0.net
そしてRustがなぜ今回の構文の形を採用したか
・returnでもbreakでも多重になった時にどれを終えるのか曖昧になるため何らかの指定は必要
・ラベルによる指定はRustの他の構文でも共通に既に使われており親和性がある
・returnの使用は混乱を防ぐために関数とクロージャーから返る位置付けのみに保ちたい
・既存のloop式と今回の構文はloopキーワードを除けば全く同じであり導入前はloop式で代替されていた

493:デフォルトの名無しさん
23/02/10 07:54:41.21 Fpp4vOr0.net
>>489
必要性に応じて関数として切り出すのも構わない
そして関数として分離した方が好ましい場合もあるだろう
しかし常に関数切り出しを強いられる言語だったとしたら煩雑すぎて機能不足と言えるから使い分けできることが必要

494:デフォルトの名無しさん
23/02/10 08:05:40.53 nOIBi0US.net
>>491
文脈読めなさ過ぎw

495:デフォルトの名無しさん
23/02/10 08:18:49.59 Fpp4vOr0.net
>>494
従来からforやloop式で使われてきた早期return(離脱)つまりRustでのラベル指定break
そして今回Rust導入されたブロック式での早期return(離脱)つまり同様に構文としてはラベル指定break
それらに対して「ラベルでジャンプ」とは何を言いたいのか?

496:デフォルトの名無しさん
23/02/10 08:34:37.12 wb0Nj+xg.net
>>486
短絡orに論理orを使うのは混乱の元だから、別の専用の記号を用意して欲しいわ。

497:デフォルトの名無しさん
23/02/10 08:39:40.06 Fpp4vOr0.net
>>496
遅延評価orの型が
現在はbool型のみに制限されているから
それをOption型などにも使えるようにしよう!という話じゃないかな

498:デフォルトの名無しさん
23/02/10 08:41:20.86 KiCBMwJT.net
>>490
関数に切り出した時点で「その範囲のResultの型」を考慮しなくちゃいけなくなるから?演算子では何も解決してないし、
切り出さなきゃ元からその関数の処理だから何もやばくないぞ

499:デフォルトの名無しさん
23/02/10 08:50:58.78 Fpp4vOr0.net
関数切り出しすると
その中でも継続して使う変数(値)を参照として全て渡してそれらの型宣言も改めて行なってと煩雑さとコードの重複が大きい
もちろん返り値型も型推論で済まなくなり明確に宣言しなければならなくなる

したがって関数切り出しの方が明確にメリットが上回るケースを除いて
適材適所でブロック式で済ませられるようになった今回の導入は大きな意義があると思う

500:デフォルトの名無しさん
23/02/10 09:14:00.68 8y57Q10t.net
関数切り出しじゃなくて、関数のネスト

501:デフォルトの名無しさん
23/02/10 09:39:52.23 FTCkglUc.net
>>491
動作も意味も全く同じとのことだが
その構文でネストしたブロックから抜けられるのかい?

502:デフォルトの名無しさん
23/02/10 09:47:31.36 XC30Ey72.net
>>496
今も||は「短絡論理OR」で区別されてないよ
短絡論理ORと論理ORを分けてる言語ってある?

503:デフォルトの名無しさん
23/02/10 09:58:49.88 zTpuYOFQ.net
5年もの歳月を費やしてstabilizeするほど意味ある機能じゃないよな
超ニッチなnice to haveなんだからこんな機能実装するくらいなら他の作業してくれよ

504:デフォルトの名無しさん
23/02/10 09:58:58.37 f/xkkyji.net
>>500
Rustで関数のネスト定義は可能だけどスコープを親関数内に限定するだけだよね
親関数の変数をもちろん操作できないので改めて引数も戻り値も全て型宣言して受け渡ししなければならない

505:デフォルトの名無しさん
23/02/10 10:00:29.07 76BGvvFm.net
>>500
関数のネストでやるためには
関数に切り出す必要があるから同じことを言ってるんじゃない?

506:デフォルトの名無しさん
23/02/10 10:06:08.19 f/xkkyji.net
>>501
forやloopを使ったときにどのbreakか区別できるようにラベルが付いてるだけでラベル付ブロック式のネストまでは元々求められていないんじゃないかな
たまたまラベル付となったからネストさせて指定して抜けることも可能なのかも知れないけどさ

507:デフォルトの名無しさん
23/02/10 11:35:14.97 D7CjmUqS.net
>>506
指定したラベル位置に制御を移すような動きのことを一般的にはジャンプと呼ぶ
ラベルで指定したブロックを”抜ける”と呼ぶ感覚ももちろん理解できるが同じようにジャンプと呼ぶ感覚くらいは理解してやれって話


次ページ
最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch