X



Rust part19
レス数が1000を超えています。これ以上書き込みはできません。
0001デフォルトの名無しさん
垢版 |
2023/01/17(火) 12:41:32.25ID:nikBFIMQ
公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust

公式ドキュメント
https://www.rust-lang.org/learn

Web上の実行環境
https://play.rust-lang.org

※Rustを学びたい人はまず最初に公式のThe Bookを読むこと
https://doc.rust-lang.org/book/

※Rustを学ぶ際に犯しがちな12の過ち
https://dystroy.org/blog/how-not-to-learn-rust

※Rustのasyncについて知りたければ「async-book」は必読
https://rust-lang.github.io/async-book/

※次スレは原則>>980が立てること

前スレ
Rust part18
https://mevius.5ch.net/test/read.cgi/tech/1670663822/
0003デフォルトの名無しさん
垢版 |
2023/01/17(火) 14:00:56.91ID:MqwPrlrO
89 それでも動く名無し 2023/01/10(火) 23:26:51.53 ID:pA5+SQtP0
痴漢ものAVと違ってこういうガチ痴漢は臨場感が違うわ
抵抗されて上手く行かなかったり、たまに他の客にバレて逃走してるからな
マジで興奮する
https://i.imgur.com/My4nuB1.jpg
https://i.imgur.com/ttXkWGH.jpg
https://i.imgur.com/upphmaU.jpg
https://gcol;le.net/product_info.php/products_id/763929/ref/15062/affiliate_banner_id/1

520 名無しさん@ピンキー sage 2023/01/03(火) 21:36:57.85 ID:AS4vmq4R0
不朽の名作が復活していたので
https://i.imgur.com/SGsDTp5.jpg
https://i.imgur.com/4R20ojB.jpg
https://gcol;le.net/product_info.php/products_id/863650/ref/15062/affiliate_banner_id/1
0005デフォルトの名無しさん
垢版 |
2023/01/17(火) 14:04:39.15ID:QD1aLS8A
   . :::';;;;: . .     ..,,,;;:
   . . :;;;;;:.:;;,,    ..:.;;;;.:
   :;;'''  .:';;; . .  .:.:;;;;;':. . .        .,,,,;,,...,,
      .:;;;' :   .:;;;;; .: ,,,;;;,,,   ,  .:;;;';;''' ''';;;;,,
     . :.;;;;' . .:   ;;;;;;;;'''' ';;;:.:.. ,;: . .    ''''''"
     ';;:;'     '''';   .:.';;;;,,;;.
                 '''  ,.:.:';;;;,,,,
             ,、—-、    .;.';:;.:.: ;;;;;;:.;.;...
   -、_      (_二ニ=っ,、;;;:.:;.:;...:.:...'''''''''''
     `‐-、_  (  ´∀)f、 `''、:..:.:. .:
         `-,ノ   つ; /
         (〇  〈-`'"
         (_,ゝ  ) `‐-、_
           (__)     `'‐-、,_..
                        `‐-、._
0007デフォルトの名無しさん
垢版 |
2023/01/17(火) 14:31:29.73ID:AjT+2M0N
最低だな
犯罪者予備軍やん
0012デフォルトの名無しさん
垢版 |
2023/01/18(水) 20:15:50.70ID:CRD98AUE
ResultがErrの時だけブロックを実行するifってどうやって書けばいいの?
if Err(_) = fs::read_to_string("foo.txt") { err() }
は通らないようだが
0015デフォルトの名無しさん
垢版 |
2023/01/19(木) 04:27:00.05ID:UpsgRjC+
>>12
エラーが起きた時は先に判断してreturnして
そうでなく正常値が得られた時はlet代入してインデントを下げずに書けないかな?
0016デフォルトの名無しさん
垢版 |
2023/01/19(木) 07:51:52.20ID:kHXiKnOP
>>15
それが少し前に入ってみんな喜んでた let else だね。

let Ok(value) = result else { return };
/* Ok のときやりたい処理 */

みたいにエラーは早期リターンして、正常系をインデント下げて書くみたいなことができる。

俺は Err は anyhow で呼び出し側に返しちゃう事が多いから正直あまり使わないけど。
0017デフォルトの名無しさん
垢版 |
2023/01/19(木) 10:36:41.67ID:pws6L0p3
Option/Result系は?演算子で素直に返すしそれ以外でもResultを返す関数に切り出して呼び出し側で?演算子にするからlet-elseは使い所がよく分からん
0018デフォルトの名無しさん
垢版 |
2023/01/19(木) 11:05:24.00ID:MVgEnHGb
>>15
そもそもreturnしない。err()の中身はエラーメッセージを出力後にパニックさせるので一方通行
0019デフォルトの名無しさん
垢版 |
2023/01/19(木) 13:52:46.10ID:i8wJP128
expectじゃだめなのかな?
もう少しちゃんとしたロギングをしたいならlog crate使ってlog_expectみたいな形でunwrap
0020デフォルトの名無しさん
垢版 |
2023/01/19(木) 14:21:48.46ID:plizw9iy
自分で書いといてあれだからやっばりexpect使うケースじゃないな
panicさせるよりもErrのまま最上位まで返してそこでログ出力含めてハンドリング
0021デフォルトの名無しさん
垢版 |
2023/01/19(木) 18:44:58.53ID:kHXiKnOP
expectってライブラリの動作確認とかサンプルコードとか、トップレベルで雑なことしたいとき以外使わなくない?

深めの階層で見かけたら身構えちゃいそう。
0022デフォルトの名無しさん
垢版 |
2023/01/19(木) 19:25:25.54ID:UlqzrrZi
論理的に安全にunwrapできるってわかってる箇所には使うかな
もしパニックになるならそもそも致命的な論理バグがあるってことになるから
変にエラー処理するより早期に落とした方がいいってケース
0023デフォルトの名無しさん
垢版 |
2023/01/19(木) 20:03:32.07ID:KyLvYp+m
横からですまんが安全なら unwrap() でよくない?
expect() にする理由ってなんだろう
0024デフォルトの名無しさん
垢版 |
2023/01/19(木) 20:30:48.24ID:UlqzrrZi
個人的には Regex::new(r"").unwrap() みたいに自明ならunwrap
安全にunwrapできる理由を書きたいならコメントに書くよりexpectに書くかな
0025デフォルトの名無しさん
垢版 |
2023/01/19(木) 20:45:59.09ID:kHXiKnOP
なるほどね。自明な時に unwrap したいけど、仮に起きたときに原因調査しやすいよう expect というのは納得できる。
0026デフォルトの名無しさん
垢版 |
2023/01/19(木) 20:51:26.80ID:kHXiKnOP
あ、違うか。unwrapできる理由を書くわけか。

paniced at 'ここでは 0 は渡ってこないので自信を持って除算する'

みたいな出力になるから割と恥ずかしいな。
0028はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/01/19(木) 22:24:19.09ID:uAmZfzQm
>>27
自分意外が使う前提のときのほうが except が必要だと思う。

外部から与えられる情報が仕様外の場合 (事前条件が満たされない場合) など
使い方が誤っているときに起こりえるなら except で説明があったほうがいいんじゃない?

内部的なロジック的に起こりえないと確信しているところは unwrap でいいと思う。
間違いがあったときに panic! してくれることには変わりないしバックトレースも出せるんで、
特に必要だと思う箇所だけ説明を付けておけば十分でしょ。
0029デフォルトの名無しさん
垢版 |
2023/01/19(木) 22:58:51.51ID:TbDEskmg
>>26
関係ないけどpanicに-ed、-ingつけるとkが差し込まれてpanicked、panickingになる
自分もRust触るまで知らなかった
0030デフォルトの名無しさん
垢版 |
2023/01/20(金) 00:14:17.87ID:+VmzUJ32
Optionを返す関数が2つ(以上)あり、
Someを得られるまで遅延評価で順に試す場合に、
func1(arg)
.or_else(|| func2(arg))
と非対称で手間なのを改善する方法ありますか?
例えば func1(arg) || func2(arg) と書けると便利だと思いました
0032デフォルトの名無しさん
垢版 |
2023/01/20(金) 02:52:18.79ID:rWEP7xyW
>>30
ないんじゃね
何回も書く必要があるなら単に関数化する
||演算子で書きたければマクロ内独自文法作る
0033デフォルトの名無しさん
垢版 |
2023/01/20(金) 11:05:21.77ID:cF/QvtGv
>>20
今だいたいそうなっていてmainにエラー出力用のコードが散在している状態
エラーメッセージの出力先もコンソールのみじゃないのでexpectだと難しい気が
0035デフォルトの名無しさん
垢版 |
2023/01/20(金) 21:59:08.95ID:A12k25he
>>33
いろんな問題をごちゃ混ぜにしすぎ
頭とコードを整理しよう
0036デフォルトの名無しさん
垢版 |
2023/01/21(土) 14:16:15.90ID:tEFzN85r
1.すべてmainまで返してmainでエラー処理をする
2.エラー処理用の関数を作ってそれを呼び出す
3.パニックハンドラでエラーメッセージを出力
くらいしか思いつかん。ググってもThe Bookに書いてある程度のことしか出てこなくて参考にならない
3はpanic!やexpectで脱出できるのは楽だけどハンドラへ渡せるデータが文字列のみでなのがいまいち
またエラー処理に必要な情報を文字列にエンコードする必要がある
2ならmainまで戻らずともエラー処理できるのでこの方向で実装中
0037デフォルトの名無しさん
垢版 |
2023/01/21(土) 14:57:31.49ID:hb5eMxVX
log crateやtrace crateはチェック済み?
logは準標準、実装は好きなのを選ぶ必要がある
traceはtokio-rs製
0038デフォルトの名無しさん
垢版 |
2023/01/21(土) 16:41:16.71ID:3Tq4pZe4
>>32
|オペレータのstd::ops::BitOrトレイトのように
||オペレータのトレイトをRustコンパイラが用意してくれたらOptionも||で扱えそう
0039デフォルトの名無しさん
垢版 |
2023/01/21(土) 18:30:23.18ID:/bIQjlWu
>>37
info!やerror!ってpanic!やexpectと本質的に変わらないような。いずれにしろ呼び出し側で文字列の加工が必要
GUIへの対応方法もよくわからない。開発時はもちろんコンソールへの出力を使うけど
運用中のエラー出力はGUIのポップアップメッセージがメインになるし

あとソースコードは600行弱くらいだけどリリースビルドで生成されるバイナリは800KB弱もあるんで
これ以上でかくしたくないというのもある
0040デフォルトの名無しさん
垢版 |
2023/01/21(土) 22:40:10.67ID:wag66I/R
ロガーを設定/生成するコード
ロガーを使うコード
ロガー自体のコード
それぞれ分けて考える

ロガーを使うコードではファイル出力だろうが標準出力だろうがinfo!やerror!でコードを変える必要はない
使うロガーを変えたり設定を変えたりする

ロギングライブラリを使うのは自前で作るのは面倒だから
0041デフォルトの名無しさん
垢版 |
2023/01/22(日) 02:33:12.00ID:5IaN6zUW
書籍で最初に読むとしたら
平家蟹の方?
それとも可愛い方?
0043デフォルトの名無しさん
垢版 |
2023/01/22(日) 02:46:40.77ID:4BdfAMug
>>39
>GUIへの対応方法もよくわからない。
GUIのレイヤーまでResultを戻してErrならエラー表示をするだけ
0044デフォルトの名無しさん
垢版 |
2023/01/22(日) 12:43:00.06ID:WLCvNrGP
>>39
ログはログ。何が起きたか記録するだけ。ログレベルが何であれ副作用は起こさない。
エラーはエラー。発生したときにどうハンドリングするかはプログラムの性質で決める。
パニックはそのまま稼働したらまずい状況に陥ったら時だけ起こす。
0045デフォルトの名無しさん
垢版 |
2023/01/22(日) 14:52:04.22ID:RMpOCJx1
>>41
モンタギュー蟹の方
0046デフォルトの名無しさん
垢版 |
2023/01/22(日) 15:29:33.81ID:WCVJRVcD
アプリケーションのレイヤーでパニック起こすのはバグの時だけ
0048デフォルトの名無しさん
垢版 |
2023/01/25(水) 16:35:00.31ID:LG3Fy/yw
うっわすっげー読みやすいコードと思ってよく見てみたら
過去に自分が書いたやつだった(´・ω・`)
0051デフォルトの名無しさん
垢版 |
2023/01/25(水) 17:17:39.71ID:xORIlv/9
過去のことを忘れていても過去の自分が考えることは今の自分が考えることとあまり差がない。
名前の付け方とかは何度考えても同じような状況なら同じ名前を付けるし。

書くときに想定する読み手が全くの他人のときと未来の自分のときではちょっと違う意識があるな。
0052デフォルトの名無しさん
垢版 |
2023/01/25(水) 18:36:03.64ID:V9gmFqbx
一度も使ったことがない機能は書くことはできても読めると思うな、が基本
使ってから読め
0053デフォルトの名無しさん
垢版 |
2023/01/25(水) 19:53:08.97ID:sck5kayB
>>47
ネットワークこそ途中で途切れること前提に書かないといけない機能の最たるものだろ。エラー返してハンドリングしろ。
0054デフォルトの名無しさん
垢版 |
2023/01/25(水) 20:37:11.28ID:5EKz9Dxo
>>48
あるあるだね
0055デフォルトの名無しさん
垢版 |
2023/01/25(水) 20:38:19.94ID:xtWPaGBn
>>47
なんでpanicになるの?
0058デフォルトの名無しさん
垢版 |
2023/01/26(木) 00:47:59.28ID:Oik+f0Gv
bool以外でもifを使えるといえばif letで
elseを省略することで3項ではなく2項演算のようになるのも&&と同じ
だがelseを省略できても{}を省略できなければ意味がない
0059デフォルトの名無しさん
垢版 |
2023/01/26(木) 11:05:43.50ID:G0iCERKY
>>58
もうちょっと基礎を勉強してからレスしろ
0061デフォルトの名無しさん
垢版 |
2023/01/26(木) 11:24:13.84ID:DDvWU5a2
>>60
これはもっともな疑問

The Bookのどこかに書いてたように思うけど
ざっくり言えばprintlnはreferenceを取るから所有権は移動しない

DisplayトレイトやDebugトレイトのメソッドシグニチャを見ると分かる
0062デフォルトの名無しさん
垢版 |
2023/01/26(木) 11:33:53.75ID:Y60o/Mze
>>60
ついこないだ Teratail で同じような質問を見たぞ。
マクロは構文糖を作り出す仕組みなので展開形によっては所有権を取ることも借用なことも何にも使いすらしないということもある。
0063デフォルトの名無しさん
垢版 |
2023/01/26(木) 14:03:27.91ID:YuUaXpq9
ある関数の&mut T型の引数として、T型の変数を貸すのは分かるけど
&mut T型の変数を又貸しするのが不思議
なぜmoveしたことにならないのか
0065デフォルトの名無しさん
垢版 |
2023/01/26(木) 15:35:28.34ID:SkvAt80a
>>63
implicit reborrowのことかな?
&mut Tの又貸しと言ってるのがどういうケースなのかはコードかないハッキリはわからないな
0067デフォルトの名無しさん
垢版 |
2023/01/26(木) 18:45:49.05ID:nglgEIPC
結局&mutを持っている間は専有しているから既存ルールに抵触することなく貸し出し自由自在という理解でいいのかな
&*でimmutableなreborrowも出来ちゃうもんね
0069デフォルトの名無しさん
垢版 |
2023/01/26(木) 19:50:53.34ID:uBPDOaY+
暗黙で参照が外されることがあるからわかりにくいんだろうな
最初から暗黙の参照外しがなければよかったと思うが
後方互換性を大事にするなら、もう改善は不可能だな
0071デフォルトの名無しさん
垢版 |
2023/01/26(木) 21:11:51.00ID:BacNCpeu
>>70
エラーを返すんだからpanicしないだろ
0072デフォルトの名無しさん
垢版 |
2023/01/26(木) 21:14:28.71ID:GObOayQz
>>68
そりゃmutならなw
0073デフォルトの名無しさん
垢版 |
2023/01/26(木) 21:18:17.56ID:q8T2WGhT
implicit reborrowはThe Bookには書かれないし直感的でもないから動きが理解しにくいというのはよく分かる
0074デフォルトの名無しさん
垢版 |
2023/01/26(木) 21:50:47.31ID:ZxPs9rBQ
>>70
例えばtwitterアプリを地下鉄とか通信できない状況で起動して panic で落ちる事を考えてみろ。そりゃバグだろ。
0076デフォルトの名無しさん
垢版 |
2023/01/26(木) 22:20:38.36ID:nglgEIPC
>>69
むしろderef含めたcoercionのおかげでRustは便利かつ読みやすいと思う
初心者の最初のうちだけは混乱するかもしれないけどそのデメリットを誤差にするほどの絶大なメリットがある
007760
垢版 |
2023/01/27(金) 11:24:22.85ID:CSClNfzp
教えてくれてるのは本当にありがたいんですが、訳がわかんないぽ・・・・
0078デフォルトの名無しさん
垢版 |
2023/01/27(金) 11:51:57.32ID:YDsF+xqw
>>77
何がわからないのか書いて
007960
垢版 |
2023/01/27(金) 13:58:30.55ID:CSClNfzp
マクロが展開するコードがあって、そこに&がついてるってことなんですか?
0080デフォルトの名無しさん
垢版 |
2023/01/27(金) 14:00:09.55ID:MqPTrKVr
せやで
Playgroundの左上のボタンでShow HIRするとマクロ展開等終わった後のコード出るから見てみ
0082デフォルトの名無しさん
垢版 |
2023/01/27(金) 21:29:03.39ID:N1uoRX56
>>74
例がtwitterアプリって...通信が出来ない状態でも何らかのオフライン操作が行えるアプリであればそうでしょうが
仕様上、エラーハンドリングを行わなければならないとされていないならバグではないでしょ....
むしろ大したログやコンソールでの情報も出さず、「エラー:通信ができましぇん」なんて返されるほうが迷惑だわ
0083デフォルトの名無しさん
垢版 |
2023/01/27(金) 21:54:30.76ID:cQ0vJjwr
>>82
バグかどうかは仕様次第というのはそりゃそうなんだけど、それじゃ建設的な議論にならんでしょ。
俺はError返しといたほうが利用側がハンドリングする余地があっていいと思うね。
0084はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/01/28(土) 02:45:04.16ID:OM0pptP0
>>82
Rust の文化にあまり詳しいわけじゃないけど panic を呼び出すのって C/C++ で言うところの assert 的なもんでしょ。
普通に考えたら panic が呼ばれるのはモジュールの仕様に対して使い方が間違っているかリカバリ不可能な場合。
逆に言えば使い方が正しくてリカバリ可能な状況で panic になるべきではない。

モジュールの使い方が完璧に正しいプログラムを書いても panic が引き起こされてしまうなら panic の使い方のほうが間違ってる。
絶対に通信が確立する状況で使えという仕様を設定すりゃあ間違ってるのは使い方のほうではあるけどさー、
ネットワークでそれは不可能な前提じゃん? ありえない前提を元にするのは不毛だろ。
0085デフォルトの名無しさん
垢版 |
2023/01/28(土) 07:46:19.92ID:NqcfPhRT
>>82
> 仕様上、エラーハンドリングを行わなければならないとされていないならバグではないでしょ....
仕様バグ...
0086デフォルトの名無しさん
垢版 |
2023/01/28(土) 09:58:07.00ID:40nYh31B
ユーザーにとって不自然な動作をすれば開発者が仕様だと言い張ったところでそれはバグだよ
0087デフォルトの名無しさん
垢版 |
2023/01/28(土) 10:54:36.16ID:9JWZ6Tol
エラーにも回復可能なエラーと不可能なエラーがあり、panicすると回復不可能な状態になるんだから、回復可能なエラーはpanicすべきじゃない。ましてや通常使用でしばしば発生する状態でpanicするのは言語道断だわな。
0088デフォルトの名無しさん
垢版 |
2023/01/28(土) 10:57:15.78ID:A5TUrW0u
assertというかexitやな。推奨はされん、普通はデバッグで面倒な時くらいじゃないか。
0091デフォルトの名無しさん
垢版 |
2023/01/28(土) 14:06:35.25ID:qTYDIi6E
マルチスレッド界隈ではスレッドの一つや二つ終了しても
回復不可能と思ってないでしょ
0092デフォルトの名無しさん
垢版 |
2023/01/28(土) 14:59:51.08ID:pTjpQsNq
The Bookにある回復不可能かどうかという判断基準は曖昧であまり役に立たない

Resultを伝播させてトップレベルでログ出力でもしてabortさせるのに比べて
問題発生箇所でpanicさせるメリットは処理をinfallibleな関数として定義出来ること

逆に言えばバグでも無いのにinfallibleな関数呼び出しでpanicで落ちるような設計はそれ自体がバグの可能性大
0093デフォルトの名無しさん
垢版 |
2023/01/28(土) 17:20:49.61ID:qTYDIi6E
0か1かではなくバグが何個あるのかも重要
落とせば一つ?
進めれば二つ以上?
0094デフォルトの名無しさん
垢版 |
2023/01/28(土) 17:59:00.91ID:b6xT90Ev
>>93
イミフ
0096デフォルトの名無しさん
垢版 |
2023/01/28(土) 21:12:57.88ID:ZIiiTUHL
>>95
イミフ その3
0098デフォルトの名無しさん
垢版 |
2023/01/28(土) 23:41:24.90ID:j4/fJAgO
自分(たち)で用いるツール類だけは
自明な前提を満たしていない場合に限り
エラー処理をサボったpanicで終わらせてもよい

それ以外のpanicは状態矛盾など続行不可禁止で発生するが
正しくエラー終了させるべきものであり
panic発生はバグと呼んでも差し支えない
0099デフォルトの名無しさん
垢版 |
2023/01/29(日) 01:28:33.47ID:K5ah9cLk
>>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系から来た人が多いのではないかな...?
0102デフォルトの名無しさん
垢版 |
2023/01/29(日) 11:17:47.92ID:p51Kojpz
panicは仕様に書いてなければバグでしょ
どんなプログラム書いてんだよ
0103デフォルトの名無しさん
垢版 |
2023/01/29(日) 11:27:06.90ID:FaEg6ckP
エラーハンドリングという言葉をpanicをハンドリングしてResultにすることだと思ってたのか
そりゃ噛み合わないわな
0105デフォルトの名無しさん
垢版 |
2023/01/29(日) 14:45:33.86ID:ttNbSKVN
問題ありまくり
同じexitがあるのにわざわざpanicで代用するメリットは何?
0107デフォルトの名無しさん
垢版 |
2023/01/29(日) 15:33:47.16ID:ZDOIjMr/
>>105
へー今初めて知った
The BookのCommon Programming Conceptsあたりにそれっぽい記述はないし
中断したければpanicするしかないと思っていたよ
後学のためにどこで解説されているのか教えてほしいな
0109デフォルトの名無しさん
垢版 |
2023/01/29(日) 17:07:54.00ID:qjfBPBdR
>>107
The Bookの12章を復習して
https://doc.rust-lang.org/book/ch12-00-an-io-project.html

ただThe Bookは他言語から来た人が最初に読むチュートリアルとして用意されてるものなのでカバーされてない内容も多々あるし深い解説がされてるわけでもない点は理解しておいた方がいいよ
0111デフォルトの名無しさん
垢版 |
2023/01/29(日) 18:20:40.83ID:yP5ym/xP
>>107
exitはプロセスの終了状態コードを伝えることを兼ねたOSシステムコールだから通常の言語には必ずある
そしてそのことを分かっていればRust初心者であってもstd::process::exitをすぐに見つけられる
0112デフォルトの名無しさん
垢版 |
2023/01/29(日) 18:41:07.89ID:qSgQK/Ke
>>105
Pythonのsys.exitと同じ感覚でstd::process::exit使うほうがはるかに問題では?
少なくとも異常終了に使う分にはpanic!のほうがsys.exitに近いと思うよ

sys.exit()
https://docs.python.org/3/library/sys.html#sys.exit
・SystemExit例外を投げるだけ
・メインスレッドで実行して、かつ例外がトップレベルまで捕捉されなければ、通常の例外機構に従ってプロセスが終了する
→finallyとかwithでリソース解放書けばちゃんと解放される

std::process::exit()
https://doc.rust-lang.org/std/process/fn.exit.html
・無条件でプロセスを終了させる
・実行スレッドも他のスレッドも一切スタック巻き戻しが行われない
→デストラクタ呼ばれない
0113デフォルトの名無しさん
垢版 |
2023/01/29(日) 18:45:14.86ID:jE2G9ZiM
_exit()はシステムコールだけどexit()はライブラリの関数
pythonのexit()やsys.exit()は基本的にexitcodeを設定してSystemExit例外を投げてるだけ
os._exit()がprocess::exit()に近い
0114デフォルトの名無しさん
垢版 |
2023/01/29(日) 18:46:31.90ID:jE2G9ZiM
>>112
例外のある言語と同じ感覚でプログラミングするのが一番の問題
それ抜きにpythonと比べとも意味ないよ
0115デフォルトの名無しさん
垢版 |
2023/01/29(日) 18:48:13.88ID:yP5ym/xP
一般的な他の言語におけるtry-throw-catchの機能が欲しいならば
それはRustやGoなどでは意図的に排除されていて存在しない
RustではResultで返すだけでよく利便性と効率を両立させている
0116デフォルトの名無しさん
垢版 |
2023/01/29(日) 19:53:25.69ID:ZDOIjMr/
>>109
そこは見ているけど制御機構を説明しているところで同時に解説すべきなのでは

>The Bookは他言語から来た人が最初に読むチュートリアルとして用意されてるもの
なおさら他言語でメジャーな機能や実装と対比した解説が必要では

>>112
unwind不可なのは使いにくい場面が少なからずありそう
今作っているのはdrop使っているから強制abortは問題しかない
0117デフォルトの名無しさん
垢版 |
2023/01/29(日) 21:27:11.45ID:yzACUqHq
RustのdropにはRcという具体的な目的がある
Rcが完璧主義ではないのでdropも完璧にする必要を感じない
0118デフォルトの名無しさん
垢版 |
2023/01/29(日) 21:32:58.27ID:ns31yZLJ
>>112
>Pythonのsys.exitと同じ感覚でstd::process::exit使うほうがはるかに問題では?

RustではResultをmainまで戻してからprocess::exitする
Pythonは例外という仕組みでランタイムがそれをやってくれる
panicはやってることがにてるからという理由で使うようなものじゃない
0119デフォルトの名無しさん
垢版 |
2023/01/29(日) 21:46:05.85ID:hfoWSJ8/
>>115
そうではないよ?例えばrustの標準ライブラリのTcpStreamにはset_read_timeoutでタイムアウトを設定すると、それ設定値以上でpanicを起こす。
これは通信中に非同期制御やスレッド監視などをしないための苦肉の策でResultをmatchするだけという考えから外れて、回復不能としているのだがリードタイムアウトであろうと再試行するようなプログラムではpanicを考慮しなければならない。
一方でTcpStreamの多くはResult<>を返すので、高度なプロトコルを作るような場合、受け取ったデータなどを調べてpanicさせる方法などが公式ドキュメントにも述べられている。
0120デフォルトの名無しさん
垢版 |
2023/01/29(日) 21:46:28.34ID:6XW+IoFB
The Bookに書いてるようにpanicを使う対象となるような回復不可能なエラーは常にバグによるもの

Rust groups errors into two major categories: recoverable and unrecoverable errors.
Unrecoverable errors are always symptoms of bugs.
0121デフォルトの名無しさん
垢版 |
2023/01/29(日) 21:56:31.01ID:saQmfbkd
>TcpStreamにはset_read_timeoutでタイムアウトを設定すると、それ設定値以上でpanicを起こす。
readで設定したtimeout値を超えたらpanicすると言ってる?
少なくともリファレンスにはResultが返されるとあるんだが
0123デフォルトの名無しさん
垢版 |
2023/01/29(日) 22:09:10.65ID:+VDCQEdm
言語の理想と実装は違うから食い違いが出ている。現実的には作者がめんどくさくなったり、ライブラリとそれを利用するレイヤーの区別があいまいな場合などに大域脱出とスタック巻き戻しがしたいだけで回復可能な場合にもpanicを投げてしまう実装もありうるのでバグではない。標準ライブラリでさえそうなのだから
0124デフォルトの名無しさん
垢版 |
2023/01/29(日) 22:14:20.10ID:jL8Axswy
> 受け取ったデータなどを調べてpanicさせる方法などが公式ドキュメントにも述べられている。
これはpanicを使えということじゃなくサンプルコードとしての簡潔さ優先してるだけ
改善はされてきてるけどunwrapがあちこちにあるのと同じ
箸の上げ下げレベルで手取り足取り教えてもらうことを期待し過ぎじゃないか
0125デフォルトの名無しさん
垢版 |
2023/01/29(日) 22:21:53.21ID:qSgQK/Ke
>>118
うん別に良いデザインではないよ、そこは同意する
俺は「同じexitがあるのに」という表現が招きかねない誤解に釘を差しただけです
0126デフォルトの名無しさん
垢版 |
2023/01/29(日) 22:33:36.00ID:+VDCQEdm
>>124
もちろんドキュメントで述べられてる通り、Resultが一番の選択肢で回復可能で返せるのにpanicを使うのは愚策でしょう。だから理想はとそういってますよね?
手取り足取り教えてもらうのはどちらなのかというよりも、どうしてもpanicで終了はバグだという理想・意見をとゴリ押ししたいだけに見えます。
これは(=回復可能なのに)panicを使えということじゃなくというのは強く同意ですが、そうなっていないものを使用している現実があるという話でpanicを書いてないことに期待し過ぎじゃないか?ということになります
0127デフォルトの名無しさん
垢版 |
2023/01/29(日) 22:38:36.38ID:yP5ym/xP
>>119
Rustでそのような形のpanicの使われ方はしませんしpanicは起きません
タイムアウトもio::Resultでio::Errorが返るだけです

これはC言語で書いてSO_RCVTIMEOでタイムアウト値を設定してreadで-1とerrnoが返る時と全く同じ状況です
言語独自の例外機構を持つ言語は複雑にしてややこしくしているだけなのでその考えをまず捨てるところからスタートしましょう
0128デフォルトの名無しさん
垢版 |
2023/01/29(日) 22:44:10.80ID:yP5ym/xP
>>126
今回のケースでも標準ライブラリはpanicを起こしていませんしpanicを起こす仕様はありません
もしpanicが起きたのならばそれはあなたがResultの処理をせずに強引にunwrap()したためであり
あなたのコードがpanicを引き起こしたのです
0129デフォルトの名無しさん
垢版 |
2023/01/29(日) 22:49:39.52ID:ZDOIjMr/
The BookにmainまでResultで戻す実践的な設計方法って解説されてる?
機能の説明はあっても実装するうえでどのようにしたらいいのかってところは抜けているような
ググるとstd::num::*を返す例、Stringを返す例、enumを返す例などが出てくるが
どのように使い分ければいいのかって点は不明
このスレ見ていてもこの部分に関する資料を提示している人は見かけないし

>>124
>箸の上げ下げレベルで手取り足取り教えてもらうことを期待し過ぎじゃないか
箸文化圏なら要らないだろうがスプーン・フォーク文化圏なら要るんじゃね
他所と大きく違うのであれば十分な説明を求められるのは当然では
0130デフォルトの名無しさん
垢版 |
2023/01/29(日) 22:51:25.05ID:CZoRokqJ
> 例には、不正なデータを渡されたパーサとか、 訪問制限に引っかかったことを示唆するステータスを返す
> HTTPリクエストなどが挙げられます。 このような場合には、呼び出し側が問題の処理方法を決定できる
> ようにResultを返してこの悪い状態を委譲して、 失敗が予想される可能性であることを示唆するべきです。
> panic!を呼び出すことは、 これらのケースでは最善策ではないでしょう。
0131デフォルトの名無しさん
垢版 |
2023/01/29(日) 23:19:15.93ID:B9jwmLl6
>>129
mainまでResultで戻すにはResult型を返す関数を書くだけ
何も難しいことはなく複雑なこともなくシンプル
Resultは単なる型の一つでOk値とErr値のEnumに過ぎない
Rust言語はResultに対し例外機構のような特別扱いをしていない
ResultはTryをimplしてるから『?』オペレータを適用できるなどくらいしか他の型との違いはない
したがって新たに勉強すべき点はそこだけだが『?』は使わずとも同じことを記述することができる
0133デフォルトの名無しさん
垢版 |
2023/01/29(日) 23:45:24.52ID:B9jwmLl6
>>132
特別扱いはないので自由
例えばbool相当としてResult<(),()>型を使ってももちろん機能する
またOption<T>相当としてResult<T,()>型
通常はそれぞれ前者を使って必要なところで初めてResultへ変換が普通
0134デフォルトの名無しさん
垢版 |
2023/01/29(日) 23:50:28.46ID:X9CS5Y/7
>>129
> The BookにmainまでResultで戻す実践的な設計方法って解説されてる?
12章はどうだろうか、minigrep を作るところ
0135デフォルトの名無しさん
垢版 |
2023/01/29(日) 23:59:14.71ID:/s+aPXiv
>>129
12章に書いてるでしょ

それに一連のレスで書いてる設計指針はRust特有の話じゃないよ
アプリのトップレベルに集約エラーハンドラを用意するのは例外機構のある他の言語でも同じだし
エラー発生時にexitcodeを設定してプロセス終了させるのはUIに相当するレイヤーの仕事だからそこまで戻してハンドリングするのも他の言語でも同じ
pythonだとしてもいろんなレイヤーでsys.exitするのは典型的なダメなやり方
0136デフォルトの名無しさん
垢版 |
2023/01/29(日) 23:59:23.38ID:B9jwmLl6
RustはResultを特別視しない
例えばGoのようにRustで(正常値, エラー値)とタプルで返す関数群でプログラミングしても同様に動く
じゃあなぜResultを用いるのか?
・統一した型があった方がいい
・二値ではなく二種のEnumでよい
・便利なメソッド群を標準で用意できる
・標準ライブラリをResultで統一できる
0137デフォルトの名無しさん
垢版 |
2023/01/30(月) 00:00:50.47ID:M6Z3pSeY
すまん被ってた
0138デフォルトの名無しさん
垢版 |
2023/01/30(月) 00:02:36.60ID:RUd1b+83
>>132
なんでEを無くしたいの?
0139デフォルトの名無しさん
垢版 |
2023/01/30(月) 00:09:50.85ID:Oa/BEQbJ
Rust特有のエラーハンドリングの実践的な知識はanyhow/thiserrorの使い方を学ぶといい
それらのcrateを使わず自前でやるとしても何を用意する必要があるのかわかる
0140デフォルトの名無しさん
垢版 |
2023/01/30(月) 00:14:09.92ID:q9Kf6jE6
副作用がない関数なら大域脱出を使うべきでないのは分かる
副作用に寛容で大域脱出に不寛容なのは分からん
0141デフォルトの名無しさん
垢版 |
2023/01/30(月) 00:19:52.36ID:1Kzq/YqA
>>139
それは初心者には混乱の元
panicとか言ってる初心者たちが最初にすべきことは一つ
「unwrap()を使わずにプログラムを書く」
0142デフォルトの名無しさん
垢版 |
2023/01/30(月) 08:11:22.12ID:sNrNLjHp
>>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でも構わないとも取れる
0144デフォルトの名無しさん
垢版 |
2023/01/30(月) 08:28:01.11ID:1Kzq/YqA
Rustをきちんと学ぶ気があるならば
まずはpanicもunwrapも使わずにプログラムを自在に書けるようになること
そういう基礎ができていないから勘違いしてpanicにこだわろうとしてしまう
0145デフォルトの名無しさん
垢版 |
2023/01/30(月) 08:31:46.93ID:uyNTp5VX
評判の悪いthe book 日本語版にすら使い分けの記述あるのに、それを無視して回復不能なエラー処理以外でpanicを推奨しようとするのは何なのかね。

エラー処理
Rustには例外が存在しません。代わりに、回復可能なエラーにはResult<T, E>値があり、 プログラムが回復不能なエラーに遭遇した時には、実行を中止するpanic!マクロがあります。
0146デフォルトの名無しさん
垢版 |
2023/01/30(月) 08:40:51.18ID:VdE13u+1
the bookを一通りきちんと読んだならunwrapは極力使うべきではないものだと理解できるはずなんだけどな
0147デフォルトの名無しさん
垢版 |
2023/01/30(月) 11:00:50.02ID:R3gVBmE3
>>138
panicで大域脱出して構わない状況ならmainで必要な情報はreturnするか否かだけ
これはResultが保持しているのでEは不要
0148デフォルトの名無しさん
垢版 |
2023/01/30(月) 11:23:44.77ID:hiS6eSAP
>>147
すまんけど全然わからない
TとEの両方がないとResultが存在できないと思うんだが
0151デフォルトの名無しさん
垢版 |
2023/01/30(月) 11:50:16.61ID:xWvH9QlK
>>149
Eをunit typeにすることをEをなしにすると言ってることは理解したが
>panicで大域脱出して構わない状況ならmainで必要な情報はreturnするか否かだけ
これは全然わからない

大域脱出したいからpanic使いたがってるという動機部分は理解した
0152デフォルトの名無しさん
垢版 |
2023/01/30(月) 12:08:29.21ID:xWvH9QlK
exitcodeをちゃんと実装したい時は
process::exitのリファレンスに書いてるように
mainの戻り値にTerminationを実装した型を指定してprocess::exitは使わずmainから戻り値を返す方法が今は推奨
0153デフォルトの名無しさん
垢版 |
2023/01/30(月) 12:56:41.01ID:WhTmZ0y4
>>151
処理継続不能なら終了するしかないからね。panicで終了しようが、mainまで戻ってからreturnしようが大差ない
0154デフォルトの名無しさん
垢版 |
2023/01/30(月) 19:01:04.95ID:uxYUj7Ri
>>153
いやいや、深いところから脱出するのにResultだと途中の階層すべてで返さないとダメだからコーディングの手間が全然違うだろ
0158デフォルトの名無しさん
垢版 |
2023/01/30(月) 19:39:30.35ID:dHwZCroo
>>154
実際にコーティングしてみれば手間はほぼないと分かる
・返り値型をResult<>で括る
・ライブラリも自作もResult返す関数を上位へスルーするなら「?」を後置
たったこれだけの話
もちろんその場で処理したいResultや情報を増やしたいResultは今回の話以前に元々処理しているはず

回復不能なエラーなんて滅多に起きず
ほとんどはその場か上位関数で何らかの対応処理するエラーなのだから
panicは滅多に必要としない
0159デフォルトの名無しさん
垢版 |
2023/01/30(月) 19:54:44.86ID:kIeP1yzV
mainまで戻るってことはmain肥大化と同義。積極的にmainを複雑化させるべきいう主張か
もちろんプログラミングの定石的には1関数にあれもこれも詰め込むのは悪手だよな
panicダメ言っている人は実用的なプログラムを書いたことがあるのだろうか
0160デフォルトの名無しさん
垢版 |
2023/01/30(月) 19:54:52.38ID:uxYUj7Ri
>>158
> たったこれだけの話
それを途中の階層全てでやらんとダメだろ
お前こそでかいプログラム組んだことないんじゃね?
そもそも途中の階層は自分が組んでるとは限らんし
0161デフォルトの名無しさん
垢版 |
2023/01/30(月) 20:06:49.02ID:Lj/9/9R5
デストラクタ内でexitを使ってはいけない
デストラクタ内で利用可能な関数の中でexitを使ってはいけない
すべての関数はexitを使ってはいけない

こういうことかな
0163デフォルトの名無しさん
垢版 |
2023/01/30(月) 20:21:20.63ID:J7344Opw
そもそもPythonのsys.exitだって本当は100点満点の正解コードを目指すなら独自例外作れって話だし
その程度の雑さでいいならRustでも雑にpanicしたっていいじゃない
教科書的な話じゃなく、もっと実利的な問題が何かあるなら教えてくれよ
0164デフォルトの名無しさん
垢版 |
2023/01/30(月) 20:22:42.83ID:1Kzq/YqA
>>159
mainまで戻る必要はない
通常は必要なところでエラー処理をする

>>160
エラー処理するところまでの途中のみでResult通過
だから手間なんてない
0168デフォルトの名無しさん
垢版 |
2023/01/30(月) 20:33:32.03ID:uC26F0Aa
>>164
> 通常は必要なところでエラー処理をする
それは回復可能なエラーの話だろ

> エラー処理するところまでの途中のみでResult通過
> だから手間なんてない
0169デフォルトの名無しさん
垢版 |
2023/01/30(月) 20:50:07.22ID:1Kzq/YqA
>>168
まともなプログラムならば回復可能か否かに関係なく各々のエラー処理をきちんと行う
そのエラー処理を最下位関数内の関数呼び出し毎に行うのではなく中位の関数である程度まとめて行う時にResult返しとそのスルーで集める
このような下位のエラー処理をまとめて行うことはRustに限らずどのプログラミング言語でも同じ
0170デフォルトの名無しさん
垢版 |
2023/01/30(月) 20:50:28.09ID:uC26F0Aa
>>164
途中で送信してしまった

> エラー処理するところまでの途中のみでResult通過
途中?
main まで帰る話はもういいのか?w
0172デフォルトの名無しさん
垢版 |
2023/01/30(月) 20:58:27.94ID:1Kzq/YqA
>>170
mainまで戻したいかどうかはそのプログラムの自由であってRustとは何ら関係がない
これは例外のある言語でも同じ
例外catchする場所はそのプログラムの自由
0174デフォルトの名無しさん
垢版 |
2023/01/30(月) 21:07:51.47ID:dHwZCroo
元々の回復不能な話はこれだけど

>>47
>> ネットワーク前提にしてる時に、panicになるのはバグではないよ?

おもちゃなプログラムを除くとそういう状態は回復不能と扱わなくて
回復不能はまず滅多に起きることではないよね
そのケースだとネットワークが使えないことを知らせて使えるようになるまでデータを維持して待つ
panicで終わらせてよいのはかなり限定された場合だけとなるよね
0175デフォルトの名無しさん
垢版 |
2023/01/30(月) 21:19:29.68ID:mdZRdLQP
回復不能連呼してる人が具体的にどんな状況でのエラーを想定してるのか説明しないのに建設的な議論になるわけがないな
0176デフォルトの名無しさん
垢版 |
2023/01/30(月) 21:38:32.03ID:jfU7NhFo
プログラムを使う側からしたら回復可能かどうかなんて些細な問題で処理できる or できないがすべて
そもそも技術的に回復可能であってもそのような実装になっていないプログラムなんて腐るほどある
0177デフォルトの名無しさん
垢版 |
2023/01/30(月) 21:42:16.22ID:1Kzq/YqA
>>173
既に書いたように回復可能か否かに関係なくエラー処理は行われる
そして上位でまとまった共通なエラー処理をする時に
途中関数での?オペレータ付加とResult返しのみでRustでは実現できる
例外機構という複雑で非効率な仕組みは必要ないという話が本題
0178デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:02:40.15ID:jfU7NhFo
>>174
>そのケースだとネットワークが使えないことを知らせて使えるようになるまでデータを維持して待つ
それは対話式のUIを持っているアプリ限定。CLIのアプリならエラーメッセージを出力して終了するのが一般的
0179デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:10:02.38ID:1Kzq/YqA
>>178
その場合でもライブラリの奥底からResult返しの連鎖があり
エラーメッセージを出力する上位まで来てからそのResult処理をする形に変わりなし
個別プログラムの方針とは関係ない共通の話がなされている
0180デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:13:28.38ID:IhW3z+yo
コマンドラインオプションでリトライ指定機能追加するときに
なんでもかんでもpanicだと泣きを見るぞ
0183デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:26:05.18ID:N/PzAAZV
fs::read_to_stringでエラーが返されたら回復不能なんでしょw
0185デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:40:43.76ID:xNQxd4Kt
>>178
curlとかリトライできたりするCLI使ったことないの?
元の質問者が>>39でGUIへの対応方法がわからないと言ってるのも本質的なエラー処理を理解せずpanicしてるからだぞ
0186デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:43:08.31ID:jfU7NhFo
>$ cat foo.txt
>cat: foo.txt: そのようなファイルやディレクトリはありません
ここで正しいファイル名を入力しろなどと言いだすCLIアプリは相当レア
0187デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:48:41.78ID:mdZRdLQP
>>186
その状況でエラー出して終了させるのは良いとして、まさかpanicさせるなんて言わないよね?
0188デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:49:07.10ID:Rt4q8oMT
>>186
$ cat foo.txt bar.txt
とでもやってみろよ
0189デフォルトの名無しさん
垢版 |
2023/01/30(月) 22:53:39.09ID:xlgBAXsb
「回復不能」って言葉がよくないんだろうな
エラーの種別についてある程度の前提知識を持ってないとなんでも恣意的に回復不能に分類しちゃう
0192デフォルトの名無しさん
垢版 |
2023/01/30(月) 23:30:11.69ID:dHwZCroo
>>183
その場合でも例えばこのように
Result処理せずにunwrap()してpanicさせたら困ることをpanic派が気付いているかどうかだよね

fn foo(path: impl AsRef<Path>) -> String {
 let text = fs::read_to_string(path).unwrap();
 // テキスト処理略
}
0193デフォルトの名無しさん
垢版 |
2023/01/30(月) 23:56:32.97ID:WvBRUZ9a
>>191
それは例外を使うべきケースと戻り値でエラーの種類を表現すべきケースの区別を例外機構のある言語を前提に語ってるもの
エラーの種別についての前提知識としては役立つがRustのResultとpanicの区別とはまた違う

その人が3種類に分類したエラーのうちPanicsだけがRustで言うところのpanicを使うケースにあたる
0194デフォルトの名無しさん
垢版 |
2023/01/30(月) 23:59:11.83ID:dHwZCroo
>>191
その文書のResultやpanicはもちろんRustのそれらとは意味が異なるよ
そして代わりに例外でエラーを返すと書かれていてもRustには例外は無いわけでw
0195デフォルトの名無しさん
垢版 |
2023/01/31(火) 00:14:04.93ID:c7ed+PvI
複おじ死んだんじゃなかったの?
いい加減コテつけてくれよな
あと新年の挨拶もまだだろ?まだ1月のうちにやっとけ
0196デフォルトの名無しさん
垢版 |
2023/01/31(火) 01:21:48.37ID:CDUXqGTR
>>194
>>193
Rustは例外が無い>try-catchやthrowが無い。
という理解で有ってます?

となると、Resultの守備範囲が広くなりそうですね。
0197デフォルトの名無しさん
垢版 |
2023/01/31(火) 04:50:14.13ID:JnYo5yDi
panic・回復不能エラーは滅多にない。
Ruby on Rails でも滅多にない

ファイルが存在しない、数値に変換できないなど、予測可能なエラーは例外。
こういうのは普通に起きるエラー

たぶん、panicを使う香具師は、書き捨てのコードだろ。
リソースの解放・後始末が面倒くさいから
0198デフォルトの名無しさん
垢版 |
2023/01/31(火) 06:55:08.97ID:YNMDboNb
>>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とか使うだろ
0199デフォルトの名無しさん
垢版 |
2023/01/31(火) 07:40:09.15ID:7I30yv0f
>>196
そう
Rustはtry throw catchの例外機構を意図的に排除している
例外機構の導入は複雑になるだけだなく効率面での不利や他の機能との相性など様々な問題がある
そのためRustやGoなどのプログラミング言語では例外機構が導入されていない

例外機構のある言語の多くでは例外が素通りする途中の関数でその宣言をしないためコードを見てもその有無が分からない問題もあった
Rustでは戻り型のResultによりそれを扱うことの有無が明確になっている
さらに"?"オペレーターによりResult値が下から上へ素通りすることも明確になっている

つまり簡素化と効率化と可読性の向上全ての両立をRustは実現している
0200デフォルトの名無しさん
垢版 |
2023/01/31(火) 07:49:11.46ID:YNMDboNb
>>199
> 例外機構のある言語の多くでは例外が素通りする途中の関数でその宣言をしないためコードを見てもその有無が分からない問題もあった
そりゃ途中の関数にはその例外は関係ないからね
関係ないものを見る必要はない
0201デフォルトの名無しさん
垢版 |
2023/01/31(火) 07:53:28.80ID:7I30yv0f
>>200
コードレビューやリファクタリングや移植作業をしたことがあればそれがコードに見えないことは非常に困ると分かる
Rustはそれがはっきりと分かるため可読性が良い
0202デフォルトの名無しさん
垢版 |
2023/01/31(火) 07:59:50.04ID:Tm4r8coX
mainからリターンするのであればプログラムの終了に至る条件が増えるほどmainの条件分岐がでかくなる
ってことも理解できない人がpanicダメとか言っているんだね
0203デフォルトの名無しさん
垢版 |
2023/01/31(火) 08:27:46.22ID:cn1TJfcU
このスレ見ていると、Rust勉強しているのにコールスタックとかスタックフレームを理解していないやつて意外と多いのが分かるな。

そもそもmainはスタックの根元で、OSとかプログラマーから見てプログラムそのものの代表だろ。
正常なフローならmainで始まってmainで終わるのは定石であって、正常なフローを破壊するpanicは異常事態。

Rustはスタックを重視してResultとか?演算子とか整備しているんだから、わざわざ用途外でpanicを使うのはRustのコンセプトを理解できていない証拠。そんなにスタックフレームのフロー制御が嫌ならRust以外を使ったら?
0204デフォルトの名無しさん
垢版 |
2023/01/31(火) 08:35:12.13ID:7I30yv0f
>>202
そもそもpanicするのはメモリ不足くらいしかない
それも最近はtry_reserve()などpanicを避ける対応も増えてきたがまだpush_within_capacity()など安定化していないな
あと固定サイズ内でやりくりするArrayVecのtry_push()を使うこともよくある
0205デフォルトの名無しさん
垢版 |
2023/01/31(火) 08:36:17.38ID:mKWzzzcA
例外がないせいで、複数ライブラリ使うとエラー型を合成する必要があってつらいわ
0206デフォルトの名無しさん
垢版 |
2023/01/31(火) 08:39:39.26ID:08CfuspX
>>200
入れ子になった関数の途中かどうかなんて関係なく、自身が呼び出した関数から出る例外に無関係な状況など考えにくいんだが
0209デフォルトの名無しさん
垢版 |
2023/01/31(火) 08:43:45.56ID:7I30yv0f
>>205
それは"?"オペレータのところでFrom::from(err)変換が自動適用されるので変換をimplしておけばよいだけ
0210デフォルトの名無しさん
垢版 |
2023/01/31(火) 08:49:38.58ID:3fV3plkN
panic派の主張は「肥大化するとなんかダサいからエラー処理サボってpanicさせとくわ。コード量は減ってスッキリするから格好いいでしょ」という風にしか聞こえない
どれだけ肥大化しようとも想定が必要なエラー処理を省略しては駄目だろう
0211デフォルトの名無しさん
垢版 |
2023/01/31(火) 08:49:41.53ID:7I30yv0f
>>207
例外がそこを通過するのか否かそこを見ただけで分からないからレビューでもリファクタリングでも何でも不便すぎる
一方でRustはそこがはっきりしていて可読性が良い
未処理な事項があって上位へ処理を委託していると明確に分かる
0212デフォルトの名無しさん
垢版 |
2023/01/31(火) 08:51:55.45ID:LXCt1d5H
>>205
とりあえず合成したいならanyhow使えばいい
勝手に全部合成されるから使い勝手は例外と変わらんと思うよ
0213デフォルトの名無しさん
垢版 |
2023/01/31(火) 09:03:32.22ID:cRk5v+aU
>>212
anyhowで勝手に合成されたエラー型への参照をmain()のifで場合分けしようとしたけど
JSのinstanceof 演算子的な処理のやり方が分からんかったわ
0215デフォルトの名無しさん
垢版 |
2023/01/31(火) 09:12:07.56ID:YNMDboNb
>>210
panicはバグとかメモリー不足とかでどうしようない状態になったときに呼び出されるもので通常のエラー処理なんてできないってことぐらい理解しなよ
0216デフォルトの名無しさん
垢版 |
2023/01/31(火) 09:18:10.08ID:7I30yv0f
>>213
そういう使い方をしたいならば例えばライブラリA,B,Cに対してMyErrorをEnumでErrorA,ErrorB,ErrorC各収容した方が扱いやすさも効率も良い
そのEnumに格納するだけのコードimpl From<MyError> for ErrorAしておくだけで簡単
0218デフォルトの名無しさん
垢版 |
2023/01/31(火) 09:28:45.86ID:7I30yv0f
>>214
Rustでは通過する途中の関数においても"?"オペレータの有無で未処理エラーを上位へ委託しているか否かが明白に分かる
だからコードレビューがしやすいし機能追加やリファクタリングする時にも見落としがない

一方で例外機構のある多くの言語では通過する途中の関数を見ても例外が通過するのか否かすら分からない
範囲を大きく広げて探し回らないといけなくなりムダな作業も発生して不便である
0219デフォルトの名無しさん
垢版 |
2023/01/31(火) 10:14:19.93ID:PU9Vswnw
>>205
自分のcrate用にエラーenumを定義して下位のエラーはそれにwrapするんだよ
その辺を楽させてくれるのがthiserror

カスタムな例外を定義しなくてもBulit-inの例外を使い回すだけで規模の小さいプログラムなら書ける例外+継承のある言語とは違うところ
Rustの場合はioエラーのみとかじゃなければ常にエラーenumを書くようになる
0220デフォルトの名無しさん
垢版 |
2023/01/31(火) 10:15:37.08ID:YNMDboNb
>>218
だから自分が関与しない例外を調べて何をするんだ?
例外使うなら例外安全に作るのは当たり前でその関数が関与したリソースはその関数がきちんと始末することでなんの問題もないでしょ?
0221デフォルトの名無しさん
垢版 |
2023/01/31(火) 10:18:35.43ID:7I30yv0f
>>217
そこは自由度があるから自分で必要性に応じて仕様を決めるべき
完全にサボりたいならanyhow等を使えばよいがその代わりにdynによる非効率さと分類の扱いにくさがトレードオフ
0222デフォルトの名無しさん
垢版 |
2023/01/31(火) 10:29:38.37ID:7I30yv0f
>>220
中間関数は関与していないのではなくcatchしないことで例外エラーを上位へ移譲している
機能追加やリファクタリングではその処理位置が変わり得るから無関係ではなく把握する必要がある
同じことをRustならば上位への移譲があるか否かが明確に分かるため非常にやりやすい
0223デフォルトの名無しさん
垢版 |
2023/01/31(火) 10:37:25.48ID:YNMDboNb
>>222
> 機能追加やリファクタリングではその処理位置が変わり得るから無関係ではなく把握する必要がある
そりゃその関数が関与するような修正するならな、当たり前
でも全ての関数が毎回関与するわけじゃないだろ
なんかダメな理由を必死に探してるとしか思えないけど
0225デフォルトの名無しさん
垢版 |
2023/01/31(火) 11:26:55.99ID:5zDIQfkR
メモリ不足でパニックとか言っている時点で全く判かっていないの草
メモリのアロケーションに失敗した場合パニックしてもその動作は保証されない
なぜならスタックの巻き戻し中にメモリのアロケーションが試みられないことを保証するのは難しいからだ
そのアロケーションに失敗した場合に二重パニックになる
パニック時にアボートする場合は別だが、その場合はリソースやロックの開放もれが発生する可能性があるね
0226デフォルトの名無しさん
垢版 |
2023/01/31(火) 11:52:51.31ID:df6faTWR
>>225
全然ここの話を聞いてなかったけど、C++だとデストラクタは内部で例外を発生しては
ならないと決まっているから、デストラクタ内部ではメモリー不足例外も
発生させてはならない。
0227デフォルトの名無しさん
垢版 |
2023/01/31(火) 11:55:03.20ID:df6faTWR
>>226
[補足]
Java などでは、例外を投げるには throw new SomeException(); のようにするが、
C++ では、throw SomeException() のようにする。つまり、前者はヒープから、
後者はスタックから例外オブジェクトを確保する。なので、例外throwそれ自体は
メモリー不足にはならない。
0228デフォルトの名無しさん
垢版 |
2023/01/31(火) 11:56:57.46ID:eIPLUE+9
Resultでエラーを表現する一番の目的は
抜け漏れなくエラー対応してることを
シグニチャーを見ただけでわかるようにして
簡単に静的チェックができるようにするため
0231デフォルトの名無しさん
垢版 |
2023/01/31(火) 12:45:18.07ID:YNMDboNb
>>225
メモリー不足で動作が保証されないなんて常色だろ
同じくプログラマーの想定外の場合でも動作は保証できないからそういう時は余計なことしないで早期に終了させるしかない
panicってそのためのものだよ
なので個人的にはrustのスタック巻き戻しはやり過ぎだと思ってる
0233デフォルトの名無しさん
垢版 |
2023/01/31(火) 12:47:09.57ID:oegPHy5Y
panic使う人は使っても困らないような
プログラム開発してるだけ
本人が困ってないならそっとしておけ
0234デフォルトの名無しさん
垢版 |
2023/01/31(火) 12:51:11.39ID:CpP2rI02
panicを使う理由が対応コード書くのがめんどくさいとか見通しとか回復可能でも呼ぶぜってところからきた話なので
回復不能エラーで呼び出された場合とか当たり前なところ話しても議論にもならんやろ
0239デフォルトの名無しさん
垢版 |
2023/01/31(火) 15:39:37.08ID:CAp90nIJ
JavaやC#あたりの経験もなくPythonやJavaScriptしか触ったことがない層がRustをやろうとしてるんだろうな
そうでもないと説明がつかない
0240デフォルトの名無しさん
垢版 |
2023/01/31(火) 15:48:38.88ID:BgaMS/KG
言語というよりはエラー種別やドメインエラーをきちんと定義するようなアプリやシステムの開発経験がないからだと思われる
0243デフォルトの名無しさん
垢版 |
2023/01/31(火) 16:33:36.83ID:hwxs0+db
自分以外がすべて同一人物が書いたかのように見えるなら病院に行きなさいって
0244デフォルトの名無しさん
垢版 |
2023/01/31(火) 16:45:54.71ID:VKWM6Cjq
複オジ2世レベルやな
立場逆転してるのが感慨深い
0247デフォルトの名無しさん
垢版 |
2023/01/31(火) 17:26:31.56ID:5mHFhJcn
GoとかRustとか例外サポートしなくなった言語、標準でスタックトレースサポートしなくなった辛さにみんなどう対応してるのかね。

エラーメッセージで grep とか、ログからコールスタックを想像とか、かなり辛いんですけど。
0248デフォルトの名無しさん
垢版 |
2023/01/31(火) 17:30:47.95ID:fFj0kljj
スタックトレースサポートされてるぞ

だかスタックトレースないとどこでエラーが発生したかわからないような作りは見直すべき
0250デフォルトの名無しさん
垢版 |
2023/01/31(火) 18:25:09.41ID:Qz5B8C78
c++勉強しているけどやっぱりrustっていいんだな
c++の場合どのオーバーロードが足りないかもエラーをチラ見しながら勘で判断するしかない
少なくとも能力の低いワイはそうやって対処している
0251デフォルトの名無しさん
垢版 |
2023/01/31(火) 19:05:37.94ID:Tu8zoz2s
例外連呼しているくせに具体的なことを書かない時点でエアプか煽りなんだろうな
例外機構を持つ処理系はエラー処理を局所化できるメリットがある
同様のメリットをRustで得るにはどのような実装が推奨されるんかな?
0252デフォルトの名無しさん
垢版 |
2023/01/31(火) 19:31:24.49ID:p+H/rvZ9
そこまで言うなら見せてもらおうか。
スレッド間エラー転送とやらを。
0254デフォルトの名無しさん
垢版 |
2023/01/31(火) 19:41:28.43ID:7I30yv0f
>>229
Rustの利点に対して「いらない情報」と言い張るのはまるでアンチのように悪意があるなあ
可読性の向上という開発効率でのメリットと実行効率のメリットさらにスレッドやコルーチン実装のタスクからも伝播させることができるRust方式は非常に優れているよ
0256デフォルトの名無しさん
垢版 |
2023/01/31(火) 19:51:16.79ID:7I30yv0f
>>247
Rustは標準でスタックトレースをサポートとしている
何でもいいからコンパイルして実行したことあればRUST_BACKTRACE=1と環境変数をセットすれば出力すると表示されることすら知らないのは不思議
ちなみにstd::backtrace::Backtraceによって自由自在に好きなところでバックトレースをキャプチャすることも出来る
0257デフォルトの名無しさん
垢版 |
2023/01/31(火) 19:56:49.64ID:7I30yv0f
>>251
Rustでもエラー処理を上位に委託してエラー処理を一箇所に局所化できる点は全く同じ
いくら初心者でもネット上のBOOKやサンプルや書籍など見てコードを書けばすぐに分かること
0258デフォルトの名無しさん
垢版 |
2023/01/31(火) 19:58:31.81ID:iWzBLVlH
>>255
254じゃないけど、メリットは分かりやすいけどなぁ。
関数のインターフェイスに、関数の作用に関する情報がまとまっていたらそりゃ便利だろう。

例外を投げる関数の場合、例外に関する情報は関数のマニュアルを参照するかソースを参照するしかないことがほとんどじゃない?インターフェイスを見ただけで例外を把握できる言語てあったっけ?
0259デフォルトの名無しさん
垢版 |
2023/01/31(火) 20:06:28.07ID:0vRdrBrN
ML系の系譜の言語はまあ大体そうなんじゃね

そしてRustでもdyn Errorで返されたら結局同じことやらされる羽目に……
0261デフォルトの名無しさん
垢版 |
2023/01/31(火) 20:25:27.93ID:QTaicIN8
>>260
マジでそれ言ってるの? マジで?

例外を無視しても「例外が投げられる」という作用は消えないよ?
例外が投げられても「俺関与しないから」と言って無視するの?
0262デフォルトの名無しさん
垢版 |
2023/01/31(火) 20:27:00.46ID:1QZESm3t
例外に関与しないってどういう意味なんだろう?
ガン無視するって言ってるんだろうか?
0263デフォルトの名無しさん
垢版 |
2023/01/31(火) 20:36:05.54ID:YNMDboNb
>>261-262
いちいち曲解するなよ
下位で発生した例外は何もしなければそのまま上位に伝搬するだろ
例外安全に作られてればその関数で確保したリソースはちゃんと解放される
それは下位の例外の種類に依存しない
0264デフォルトの名無しさん
垢版 |
2023/01/31(火) 21:10:03.87ID:QTaicIN8
>>263
「上位に伝達する」という意味わかっている?
>258がインターフェイスの話をしているのは理解できている?

関数の呼び出し元からすれば、呼び出し先で投げられているのか、さらにその先で投げられているのか、とか関係なく「関数を使ったら例外を投げられた」だよ。関数のユーザーからすれば「投げる例外くらい明確化するのが常識だろ」と思うよな。

関数が例外を投げるのに、その関数の作者が「例外に関与しないからオレ知らね」とか言って逃げたらブチ切れるわ。そんなんだったら例外全部catchして関数の外に漏らすな、と。
0266デフォルトの名無しさん
垢版 |
2023/01/31(火) 21:28:25.11ID:Qz/Q1rYV
Javaの検査/非検査例外以降の約20年余りの試行錯誤の結果辿り着いた現時点でのベストプラクティスを採用したのがRustやSwiftのエラー処理モデル

C → Java → C# → Go →Swift/Rust
0268デフォルトの名無しさん
垢版 |
2023/01/31(火) 21:42:42.48ID:QTaicIN8
まぁ、Result使うとしてもtry catch finallyブロックみたいなフローが欲しいというのはわからんでもない。

関数から抜ける時にResultを漏らさず処理したいというのはたまにあるし。
0269デフォルトの名無しさん
垢版 |
2023/01/31(火) 21:48:12.48ID:jD2BQUnk
>>263
catchとかしないの?回復処理したり付加情報付きの例外投げ直したり
そのためにはcatchすべき例外が上がってくるかどうか知らないといけないんだけど
0270デフォルトの名無しさん
垢版 |
2023/01/31(火) 22:04:35.47ID:WaCEL3Yw
この件でプログラミング言語が最低限サポートして欲しい点2つ

ある関数(ライブラリ)を使おうとした時に
①その関数やその子孫からエラーや例外が上がってくるのか、それとも全て処理済なのか?
これが奥深く辿らなくても局所的に把握できること
ドキュメントベースはそのミスや見落としが生じるため不可
②エラーや例外が下から上がってくる関数を用いた時に、
その処理をせずに続行してしまうコードを書いてしまったら、実行前に言語システムにより防げること

例えばRustならば①は返値がResult型かどうかですぐに把握できる
②は型システムによりRustコンパイラが型不一致や未処理放置Resultの存在を伝えてくれる
Rustは現在ベストなプログラミング言語と言い切っても過言ではない
0271デフォルトの名無しさん
垢版 |
2023/01/31(火) 22:16:44.29ID:Mxurit6u
>>270
高い信頼性が要求されないプログラムなら
例外と集約エラーハンドラさえあればいいんだから
Rust的なモデルが最適化どうかは要件次第だよ
結局はトレードオフ
0273デフォルトの名無しさん
垢版 |
2023/01/31(火) 22:45:41.29ID:WaCEL3Yw
>>271
趣味のおもちゃプログラムでなければ信頼性は必須だよね
それだけでなく>>270の最低限の2点はプログラマーにとっても必要なこと
①を満たせない言語では無駄に調べまくらなければいけない
②を満たせない言語では無駄に実行時デバッグを強いられる
トレードオフと言われても信頼性と開発効率を両方落とすのは割に合わない
0274デフォルトの名無しさん
垢版 |
2023/01/31(火) 23:47:23.84ID:ovWek0QN
使いたい関数だけじゃなくて、その関数が使ってる関数、更にその関数が、、、って調べていかないといけないのが無駄にコスト高になるんだよね。
0276デフォルトの名無しさん
垢版 |
2023/02/01(水) 00:33:02.66ID:CK4ZTpUy
やっぱ複オジは成長しねーな
2世と同類だわ
0278デフォルトの名無しさん
垢版 |
2023/02/01(水) 06:17:22.82ID:5NtLPUR3
>>275
Rustならば使う関数のシグネチャを見ればResultが返ることで>>270の①を知ることができるけど
例外機構の言語の多くはシグネチャには情報がないため完全に信頼できるドキュメントでもない限り下流の関数全調査になるかな
②の処理忘れ防止機能も含めてRustが最も整備されている言語という感じ
0279デフォルトの名無しさん
垢版 |
2023/02/01(水) 07:12:22.77ID:Hf88nfPH
>>264
だから上がってくる例外を処理する必要があるならその時に調べればいいでしょ?
例えばprintfみたいな関数作ってる時に下位のputsみたいな関数がI/Oエラーで例外上げてくるだろうけどそれはそのまま上位にあげるだけだろ
いちいち意識する必要はない

>>265
強い保証の意味がよくわからんが自前でキャッチして処理すれば良くね?

>>269
全ての関数で回復処理が必要なわけじゃないし情報を付加するだけなら例外の種類を問わずにキャッチしてスローすればいいでしょ
すべての階層で事細かく例外をキャッチしてスローし直すなんてことは普通やらないよ
0280デフォルトの名無しさん
垢版 |
2023/02/01(水) 07:21:02.47ID:Hf88nfPH
>>270
言いたいことはわかるけどそれを実現する手間が掛かりすぎると思う
そもそも例外を上げるかどうかだけを見たいならnoexceptを真面目に実装すればいいだけだし
0281デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:02:53.27ID:5NtLPUR3
>>280
それを実現する手間が掛かりすぎる、という視点がむしろ既に間違えているのかもね
従来の例外の枠組みを持たずにRustは>>270の二点をシンプルで効率よく実現してしまった
つまり従来の例外の枠組みよりも利便性と信頼性の高い新たな枠組みが実用的だと示されたのだから
従来の例外の枠組みを捨てるべき時が訪れたと解釈する方が正しいのかもしれない
0282デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:17:31.54ID:rokbXrwB
>>272
あ、漏らさず処理はできるな。ごめん。

言いたいのは「似たようなエラーをまとめておいて、修正も一括で行う」のイメージだった。
例えば「関数内で細切れでファイルに書き込んでいるとき、どこかで書き込みエラーが出たらロールバックしてログを取って再書き込みする」とか。

>>279
やっぱり全然理解できていないな。
その「printfみたいな関数」を使う「上位」のプログラマーはどうすんだよ。「例外に関与しないからオレ知らね」か?
そんなんだったら例外全部catchして関数の外に漏らすな。
0283デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:17:38.20ID:Hf88nfPH
>>281
> 従来の例外の枠組みを持たずにRustは>>270の二点をシンプルで効率よく実現してしまった
シンプルだけど生産効率は良くないよね?
って言ってるんだけど...
0284デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:20:02.84ID:Hf88nfPH
>>282
上位で処理する必要があるならその時に調べればいいだろ
途中の関数で逐一調べる必要はない
そもそも最下位の関数に新しいエラーが定義されたらrust使いは全部調べ直すのか?
0285デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:25:05.41ID:ATJMUMOg
>>279
その調べるかどうかをどう判断するかって話なんだが…
putsがI/Oエラーを上げてくるって知ってるから無視して上に上げるって判断ができるわけ
じゃあライブラリXの関数Yは無視すべきなのかそうでないのか?ってこと
0286デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:27:52.62ID:rokbXrwB
>>284
どうやって調べるのか、具体的に考えた?
インターフェイスしか提供されていなくて、ソースコードの無いライブラリとかでどうやって調べるの?

エスパーか神様でもなければ不可能だね。
0287デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:30:01.09ID:5NtLPUR3
>>283
むしろ>>270の二点をサポートしているRustは開発効率が高いでしょう
それらをサポート出来ていない従来のプログラミング言語は開発効率も信頼性も低いわけです
開発効率と実行効率と信頼性の高さを両立させたRustの地位は揺るぎないと思われます
0288デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:37:05.02ID:rokbXrwB
ダックタイプ系の開発効率を求めるならRustは選択すべきじゃないよね。メモリの取り扱い見ればRustは「作法を強制する言語」だということは明らか。
そういうのはPythonとかRubyとかスクリプト言語があるんだからそっちを選ぶべき。
0289デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:41:21.89ID:wznv5J1H
>> 279
> 強い保証の意味がよくわからんが自前でキャッチして処理すれば良くね?
他は既に突っ込まれてるから言わんが
例外に関するプログラミングしてたらすぐにわかる概念だからググれ
つうか例外安全って言葉使うなら知っとけ
0290デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:54:40.02ID:Hf88nfPH
>>285
例えばprintfみたいな関数で下位の例外を処理するのか?
処理するとして何をやるんだ?
って話
考え方が逆なの、自分に関与しない例外は触らない

>>286
ライブラリならドキュメントに書いてあるでしょ

>>287
また呪文唱え始めたのかw
せめてこれに答えてよ
> そもそも最下位の関数に新しいエラーが定義されたらrust使いは全部調べ直すのか?
0291デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:55:45.56ID:Hf88nfPH
>>289
> 例外に関するプログラミングしてたらすぐにわかる概念だからググれ
また無能のググれかよw
答えられないなら無駄に絡んでくるなよ
0292デフォルトの名無しさん
垢版 |
2023/02/01(水) 08:58:06.40ID:ATJMUMOg
>>290
別に調べ直す必要はないよ
下位にエラーが追加されても直接呼び出す関数のシグネチャが変わらないなら対応不要、変わったら対応するってだけ
結局呼び出す関数のResult型が対応すべきもののすべてなんだからそれ以外見る必要がない
0293デフォルトの名無しさん
垢版 |
2023/02/01(水) 09:02:33.17ID:JRuvbVor
>>288
そういうCPUもメモリも浪費するエコでない言語との比較はほとんど意味がないんじゃないかな
GC言語であってもそこそこ速いJavaやGoくらいの立ち位置の言語ならば比較の意味があるとしても
0294デフォルトの名無しさん
垢版 |
2023/02/01(水) 09:20:03.74ID:JRuvbVor
>>290
> そもそも最下位の関数に新しいエラーが定義されたらrust使いは全部調べ直すのか?

Rustでそんなことをする必要がないよ
元々他のエラーも返す関数だったならば返り値型が元々Result型だから枠組みは変化なし
新たにエラーを返すように返り値型が変わったならばコンパイルエラーで気付く
0295デフォルトの名無しさん
垢版 |
2023/02/01(水) 09:26:13.19ID:ypE1x0h9
fishシェルをRustで書き直すことが(ほぼ)決まったよ
https://github.com/fish-shell/fish-shell/pull/9512

C++ と CMakeをかなり腐してるけど意外に荒れてない
ちなみに提案者は開発リーダーなのでほぼ決まりでしょう
リンクされてる移行プランは他のプロジェクトでも参考になりそう
0296デフォルトの名無しさん
垢版 |
2023/02/01(水) 12:36:36.73ID:o2DBVRIO
>>292,294
> 元々他のエラーも返す関数だったならば返り値型が元々Result型だから枠組みは変化なし
なら、その新しいエラー(例えばディスクフルを検出してたが今回ディスクオフラインなんてエラーが追加された)の処理が抜けてないことはどうやってわかるんだ?
実行時にしかわからないなら例外と変わらん
むしろ途中の伝搬コードをいちいち書くのが面倒なだけだろ
0297デフォルトの名無しさん
垢版 |
2023/02/01(水) 12:42:13.45ID:BH4poKX+
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
0298297
垢版 |
2023/02/01(水) 12:45:24.97ID:BH4poKX+
>>297
修正。内側・外側が逆だった

>throw/catch, raise でも、例外の発生場所を関数の外側から内側へ移すだけ
throw/catch, raise でも、例外の発生場所を関数の内側から外側へ移すだけ
0299デフォルトの名無しさん
垢版 |
2023/02/01(水) 14:01:39.16ID:TUW+NsdV
>>296
それはResult<T,E>のEで返されるエラーenumのvariantが増えるだけ
んでvariantが増えればEをハンドルしてるところでexhaustiveに処理してなければコンパイルエラー
0300デフォルトの名無しさん
垢版 |
2023/02/01(水) 14:08:16.76ID:w5pt5x/h
>>282
>言いたいのは「似たようなエラーをまとめておいて、修正も一括で行う」のイメージだった。
これはResultのコレクションを返せばいい
例外のある言語でもこのケースは例外じゃなくエラー情報を貯めたオブジェクトを戻り値で返してエラーがあったかどうかをチェックして分岐するコードを書く
それと似たようなもの

>例えば「関数内で細切れでファイルに書き込んでいるとき、どこかで書き込みエラーが出たらロールバックしてログを取って再書き込みする」とか。
ロールバックする系の処理ならエラーを貯めずにエラーが一つ出た時点で中断するように作ったほうがいい
0303デフォルトの名無しさん
垢版 |
2023/02/01(水) 17:49:22.59ID:HDxpsRMp
dyn Errorでできるのは

・print!とかwrite!でログ出力する
(ErrorトレイトにDebugとDisplayが内包されてるからちゃんと実装されてれば何か教えてくれる)

・source()で内部のdyn Errorを掘り起こす
(エラーの原因のエラーがあれば一緒にログ出力できる)

くらいだからログ出力以上の活用がしたいならそのためのError型を使わないといけない
0304デフォルトの名無しさん
垢版 |
2023/02/01(水) 18:15:38.74ID:pHJayYFi
>>302
具体的なエラーの型で分岐させたいならダウンキャストが必要(The Bookにも書いてたはず)
エラーenumを定義してwrapしたものに変換(map_err)しておけばダウンキャストは不要
anyhowに組み合わせてthiserrorの#[from]や#[error(transparent)]を使うと楽にwrapできる

anyhow/thiserrorのやってることに最初から自力で辿り着くのは大変だから先に使ってみて必要な要素を学んだ方が早いよ
0305デフォルトの名無しさん
垢版 |
2023/02/01(水) 19:06:46.56ID:JRuvbVor
>>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に格納する「?」時の自動変換を書いたり
それぞれ簡単で単純なパターンなのだから標準ライブラリで基礎を身に着けた上で自作や外部のライブラリを選ぶのがお勧め
0306デフォルトの名無しさん
垢版 |
2023/02/01(水) 19:07:10.38ID:sE34HuOS
>>290
例外をサポートしているような言語なら、投げる例外を関数のインターフェイスとしてドキュメントに記載する。
Rustなら>>292


>考え方が逆なの、自分に関与しない例外は触らない

>290が>285 >286を理解できない無能だということは理解できた。
c++とかでライブラリ関数からドキュメントに無い例外を投げられた経験が無いんだろうな。おめでたい。
0308デフォルトの名無しさん
垢版 |
2023/02/01(水) 19:27:56.01ID:JRuvbVor
>> ライブラリならドキュメントに書いてあるでしょ

ドキュメントは言語システムの一部ではないため
ミスで現実のコードとドキュメントが食い違っていることもあれば
ドキュメントは正しくても利用者が見落としてしまうこともある
大規模な開発になればなるほどミスや見落としが紛れ込むことは避けられない
特にエラー処理が済んでいるか未だなのかは致命的になりかねない

一方でRustは言語システムの中で下位関数からエラーが上がってくるか処理済か分かる
さらにResultが未処理のままだとRustコンパイラが指摘してくれる
言語システムとして少なくともこれらの機能を持つ言語へと今後は移行していくべき流れ
0309デフォルトの名無しさん
垢版 |
2023/02/01(水) 21:57:57.91ID:qgBIsers
>>305
>それぞれ簡単で単純なパターンなのだから
実装の簡単さやパターンの単純さが問題じゃないんだよ
Rustのエラー処理に必要な「それぞれ簡単で単純なパターン」を網羅的に知識として仕入れてRustのエラー処理はこうやってやるものだと自信を持って言えるようになるまでの学習効率の問題
anyhow/thiserrorはそのパターンを楽に使えるよう作られてるから「ああRustのエラー処理ってこうやればいいんだな」ってのが標準ライブラリ前提で学ぶより断然早く理解できる
0310デフォルトの名無しさん
垢版 |
2023/02/01(水) 22:05:04.46ID:JRuvbVor
>>309
dynの取り扱いと「?」オペレータによる自動変換はRustの基本事項で必須の知識
もちろん標準ライブラリの中で完結して使えるしシンプル仕組みなのですぐ使えるようになる
この基本を習得せずに外部ライブラリへ行くことを勧めるのは基本知識を欠いた人を生み出してしまう愚かな行為
0311デフォルトの名無しさん
垢版 |
2023/02/01(水) 22:25:39.32ID:JqtaL/Do
>>310
もしかしてパターンってdyn Errorと?オペレータ使った自動変換の話だけなの?
それだけじゃRustで現実的にどうエラー処理を実装すべきかThe Book読み終えたくらいの人にはわかんないと思うよ
0312デフォルトの名無しさん
垢版 |
2023/02/01(水) 22:59:41.62ID:JRuvbVor
>>311
エラー処理パターンは様々な方針があり
その前提知識としての共通の必須事項として今回のスレの流れで話が出て来ていたdynの取り扱いと?での自動変換の話を書いた

例えばあなたが出したanyhowはdyn Errorを扱う外部ライブラリの一種
anyhow::Errorから具体的な型を取り出すためには>>305で書いたdynの取り扱い知識が必須
この知識を知らないと細かいエラー分類が出来ずにエラー表示のみしか出来ない人になってしまう

もう一つあなたが出したthiserrorも?での自動変換を用いる外部ライブラリ(というかマクロ)の一種
>>305で示したFrom::from()による自動変換の基礎知識を欠いたままでは仕組みすら分からず魔法のように外部ライブラリを使うダメな人になってしまう
応用が効かないだけでなく利用していて何か問題にハマった時に基本知識がないと解決することもできない
0313デフォルトの名無しさん
垢版 |
2023/02/02(木) 00:32:13.04ID:y8eaHXgz
>>312
設計やプラクティスとしてのパターンのことを言ってたんだが君は言語機能のことをパターンと呼んでるみたいで噛み合ってないよね

dyn Errorや?オペレータ使ってinto経由で変換されるような基本的な機能面の知識はThe Bookにも書かれてるレベルだし多少分からなくてもリファレンス読めばいいだけの話
でもそれだけの知識でRust初心者がエラー周りの実践的な設計をできるようにはならないでしょ
0314デフォルトの名無しさん
垢版 |
2023/02/02(木) 00:53:57.92ID:tzaW+blt
anyhow/thiserrorは最近出てきた新興ライブラリ
当然それまでは誰も使っていなかったわけで初心者がいきなり必須なものでもない
初心者にとっては複雑で機能過多で理解しにくいのでまずは標準ライブラリから始めたほうが良いかな
0316デフォルトの名無しさん
垢版 |
2023/02/02(木) 03:39:28.87ID:S9qGtTXE
Rustは「教官付き教習車」だよ。
cとかと違ってアホが膝を撃ち抜く自由は許さない。
それが嫌ならRust止めれば?
0317デフォルトの名無しさん
垢版 |
2023/02/02(木) 07:11:05.90ID:02L2EQ2o
Rustはコンパイラの防波堤の中で安全な自由があるけどそれはともかく
クセの強いanyhowをRustの基本より先に初心者に教えるのはあかんよ
たとえば、他人も使うライブラリ作成ではanyhowの使用を避ける、といった当たり前のことも
エラーに関する基本を知らないと陥ってしまう
0320デフォルトの名無しさん
垢版 |
2023/02/02(木) 07:55:32.16ID:Cx26n0QZ
>>317
あれはクセというよりanyhowの致命的な欠陥だ
分かってる人は配慮して閉じた環境だけで使うけど稀に公開ライブラリにanyhow使っちゃう無知な人もいる
基礎知識はホント一番大事
0324デフォルトの名無しさん
垢版 |
2023/02/02(木) 12:40:03.75ID:8vdGQp5R
複オジが使ったことないだけだろ
>>312も今調べてきました感満載じゃん
デファクトスタンダードになってるライブラリまで排除したらrustでは何もできんぞ
0327デフォルトの名無しさん
垢版 |
2023/02/02(木) 13:20:28.44ID:C8PK02xw
禁忌事項はライブラリを作って提供する時にanyhowを使ってしまうことだけだから
そこはanyhowを使わずにthiserrorを使えばヨシ
0328デフォルトの名無しさん
垢版 |
2023/02/02(木) 15:47:50.42ID:HD9HoUeH
別にanyhowをthiserrorに差し替えるのも大した手間じゃないしな
ライブラリで使っちゃってるなら変更PRでも出してやれば良い
0329デフォルトの名無しさん
垢版 |
2023/02/02(木) 23:07:11.98ID:3wRXRcn7
>>325
anyhowとthiserrorを使うなと言ってる人は誰もいなくて
・まず先にstd::error::Errorを覚えよう
・次に?変換とdynダウンキャストを覚えよう
・そしてanyhowとthiserrorへ進もう
という話でしょ
そうすればanyhowをライブラリで使うべきでない理由もわかるでしょうし
0331デフォルトの名無しさん
垢版 |
2023/02/02(木) 23:37:26.35ID:wswA48V7
むしろRust基盤の一つ
downcastはエラー処理に限らずdyn Traitを元の型に戻すために必須
anyhowでも元のエラー型に戻すために必須
0333デフォルトの名無しさん
垢版 |
2023/02/02(木) 23:53:52.64ID:QEJ+oT50
ダウンキャストを知らないと
>>303のようにdyn Errorで出来ることはログ出力だけと思いこんでしまう
0334デフォルトの名無しさん
垢版 |
2023/02/02(木) 23:59:01.23ID:Cx26n0QZ
>>332
当たり前
Rustの標準ライブラリはunsafeだらけ
原理的にunsafeは避けられないからそれを安全なインターフェイスとして公開するのがRustの標準ライブラリ
0335デフォルトの名無しさん
垢版 |
2023/02/03(金) 00:57:17.44ID:teLYlQt8
dynを元の型に戻すという発想に違和感(気持ち悪さ)を感じる人もいると思う
元の型に戻すつもりならそもそもdynにしないというか
ダウンキャストは戻すべき型(の変更)を全部把握できる閉じた状況じゃないと使いにくい
0336デフォルトの名無しさん
垢版 |
2023/02/03(金) 01:37:41.39ID:VgIBWdEw
>>335
anyhowを使うのはそういう全部把握できる閉じた状況で
独自エラー型を用意するのが面倒な時に使うからダウンキャストが理に適っている
嫌ならanyhow使わずにthiserrorを使えばよい
0337デフォルトの名無しさん
垢版 |
2023/02/03(金) 07:58:09.95ID:+r7mcEDE
>>335
型を全て把握しておく必要はない
例えばエラー処理で大半はエラー表示のみだが一部だけ特別な処理をしたいとすると
その処理したいエラー型のみダウンキャストして使えばいい

ちなみにダウンキャストは内部で定数のu64で表現される型番号をu64比較するだけなのでコストがかかるものではない
0338デフォルトの名無しさん
垢版 |
2023/02/03(金) 08:54:57.66ID:Vma9tJMI
ダウンキャストの扱いかどうか知らんが、パターンマッチングも総和型から個別型ヘのキャストみたいなもんだろ。
0339デフォルトの名無しさん
垢版 |
2023/02/03(金) 09:11:06.24ID:+r7mcEDE
もしdyn使わずに自作Enum収容エラー型を定義して使っても
Enumタグ比較で分岐することになるから状況は似たようなもの
0341デフォルトの名無しさん
垢版 |
2023/02/03(金) 09:36:29.67ID:e19a6Rdo
初めて間もないけど
println!("{}", a);
とか手が攣って辛い
tabでもprintlnまでしかでないしコピペでもしてるの?
0342デフォルトの名無しさん
垢版 |
2023/02/03(金) 09:43:50.06ID:90dUFc67
downcastすればいいだけだからdyn Error返してもデメリットは無いってのなら
ライブラリでanyhowを使うのも大した問題じゃないって結論になるん?
0343デフォルトの名無しさん
垢版 |
2023/02/03(金) 10:26:25.61ID:5QmoSp+n
>>342
anyhowの問題点はそこではない
anyhowは最も重要なことを実装していない(不可能)という欠点があるため
0345デフォルトの名無しさん
垢版 |
2023/02/03(金) 10:48:35.31ID:yQvnFmTM
予言しよう
ググれば分かるんだから書かないとか言って絶対に具体的な説明はしないやつだよ
0346デフォルトの名無しさん
垢版 |
2023/02/03(金) 12:00:34.82ID:7ZLHWUFf
俺はなんも知らんから頭の片隅に覚えておくくらいにしとくわ
使うときに調べる
0348デフォルトの名無しさん
垢版 |
2023/02/03(金) 12:37:16.79ID:tbHpIbwJ
Rustでエラー型はstd::error::Errorトレイトを実装するのが共通のお約束だけど
anyhow::Errorは諸事情あって実装されていないんよ
std::error::Errorトレイト実装を前提として扱っているところへライブラリがanyhow::Errorを返しちゃうと困っちゃう
ライブラリを作るときはthiserrorでエラー型を作ればstd::error::Errorトレイトを自動で実装してくれるから大丈夫だよ
もちろんthiserror使わずに自分で実装してもいいよ
0350デフォルトの名無しさん
垢版 |
2023/02/03(金) 18:59:27.03ID:NDb3ccU3
Box<dyn Error>もErrorトレイト実装してないよ(コンフリクトで実装できない)
その点はdyn Errorで返してもanyhowで返しても大差ない
libraryのpublicなAPIでtype erasedなエラーを返したいときは
Errorを実装した独自のエラー型を用意するのが普通
anyhowで返してる有名ライブラリもあるけどね

ライブラリでanyhow使ったらダメなんてことは特にないんだけど
Readme読めばすぐわかるように基本的にはアプリケーション用

なぜ同じ作者のエラー系のライブラリがanyhowとthiserrorと2つあるんだろうか?
と疑問に持つだけでも初心者はstdベースで学習するよりも1歩先に進めてる
0351デフォルトの名無しさん
垢版 |
2023/02/04(土) 00:38:01.54ID:5aCWsuCk
ダウンキャストは静的チェックできず変更に弱いからホイホイ使うものじゃないよ
0352デフォルトの名無しさん
垢版 |
2023/02/04(土) 07:20:32.73ID:eqpqpGi8
>>351
ダウンキャストは静的に型を指定して
Some()で静的な型で値が返ってきて
その値の使用も静的に型チェックされる

「マッチングが動的ではないか?」については
Enumで複数の型を収容した場合と全く同じ
どちらの場合もマッチングは動的に行われるが静的に型チェックされる
どちらも静的に型を抽象化した定数の整数値との比較によるマッチングとなる点も同じ
0354デフォルトの名無しさん
垢版 |
2023/02/04(土) 09:59:08.11ID:wSUDs8sY
Rustのdynとそのdowncastは安全性と最小限のコストを両立させており安心して使える
引数などでimpl Traitが使える場合はimplが有利なケースもあるが
返値などでdyn Traitしか使えない場合もあり適材適所で使い分け
0357デフォルトの名無しさん
垢版 |
2023/02/04(土) 12:44:13.93ID:vEFKnpWX
ダウンキャストの安全性みたいなのは downcast_ref 使ってりゃ議論の余地はないと思うけど網羅性は限界があるわね。

ライブラリはやっぱエラー型を明示すべき。
0359デフォルトの名無しさん
垢版 |
2023/02/04(土) 13:39:49.84ID:A1ugYU/e
エラー処理で網羅性は関係ないだろ
std::io::Errorのenum ErrorKindからしてnon_exaustive指定だぞ
match式で網羅性はチェックされない
特別な処理が必要なエラーだけ処理対応して残りはエラー表示が普通だ
0360デフォルトの名無しさん
垢版 |
2023/02/04(土) 13:52:58.01ID:RtFCJdnN
エラー処理で重要なことは
・エラーが発生しているにも関わらずそのまま通常処理を進めないこと
・エラー表示以外の対応を必要とするエラーの場合にその対応をすること
・それ以外のエラーはエラー表示などをすること
enumタグレベルの網羅性を求められることはないな
0361デフォルトの名無しさん
垢版 |
2023/02/04(土) 14:46:52.23ID:7PnUG+Eh
元々の話はdyn Errorかanyhowか、だったような気がするけど、
anyhowはdyn Errorの自作ラッピングみたいなもので、
とちらを使ってもダウンキャストしなきゃいけない点も網羅性がない点も同じだよね。
そしてそれらをアプリ側で使ってる限り困ることもない。
0362デフォルトの名無しさん
垢版 |
2023/02/04(土) 17:06:34.73ID:1vu2ZDPp
そもそもがダックタイピングとか向いてる言語じゃない。
フロントでこの言語使おうとするとかただのバカでしかないわ。
0363デフォルトの名無しさん
垢版 |
2023/02/04(土) 17:36:37.29ID:roDrLtFP
唐突にフロントとかダックタイピングとかどうした?
しかもその二つも関連性がない
0364デフォルトの名無しさん
垢版 |
2023/02/04(土) 18:06:27.05ID:uIknpDmG
上位レイヤーも含めてエラーの内容によって分岐したいならdyn Errorはやめたほうがいい
0365デフォルトの名無しさん
垢版 |
2023/02/04(土) 18:34:38.01ID:srvPtSil
分岐にenumのタグを使うかErrorの型名を使うかの違いでしょ
enumを使うと一貫性を担保しやすいから保守性が向上するし
dyn Errorを使うとenumの定義を省略できるからコードを減らせる
自分は(分岐するなら)enum派だけど何を重視するかで結論が変わりそう
ただ「やることが一緒だからどっちも同じ」と考えはいただけない
0366デフォルトの名無しさん
垢版 |
2023/02/04(土) 18:40:15.09ID:3y1LLse5
>>364
dyn Errorをやめるべき理由がない
まさかと思うが代わりにanyhow使えとか言い出すんじゃないんだろうな?
0367デフォルトの名無しさん
垢版 |
2023/02/04(土) 19:00:20.00ID:eqpqpGi8
dyn Errorもダウンキャストも使用して全く問題ないよ
有名どころでも普通に使われている
例えばreqwestはdyn Errorを使っていてdowncast_ref()してエラー処理している
cargoはanyhowを使っていてdowncast_ref()してエラー処理している
使うのをやめたほうがいいと主張している人は一種の宗教にすぎないことに気付こう
0368デフォルトの名無しさん
垢版 |
2023/02/04(土) 22:40:19.42ID:JjHQagj1
勘違いしてる内容が同じだから
自演しまくっても同一人物なの丸分かりだね
ダウンキャストオジ==複オジ
0372デフォルトの名無しさん
垢版 |
2023/02/05(日) 06:00:11.27ID:TqN0qcyT
オライリーの本って出てから1年経つけどさあ
これの電子版って、セールになったりする機会ってあるもんなの?
0374デフォルトの名無しさん
垢版 |
2023/02/05(日) 12:11:30.30ID:vL4nY6Md
>>359-360
おまえはまるで何もわかってないのな
エラーハンドリングの基礎すらおさえてないじゃん
無知なのはいいが自信満々で嘘を書きまくるのはやめろ
0375デフォルトの名無しさん
垢版 |
2023/02/05(日) 12:37:36.14ID:yQ5U4c14
作るシステムの性質や分野ごとで許されるエラーハンドリングは別物だからね。
ミッションクリティカルだけが正解ってわけでもないのよ。
0377デフォルトの名無しさん
垢版 |
2023/02/05(日) 14:22:39.74ID:Ib1Yzzhk
たまに出てくる「間違っている」「勘違いしてる」「嘘を書くな」の人
今までも文句をつけるだけで正確を書いたことがないから信頼できないのよね
0378デフォルトの名無しさん
垢版 |
2023/02/05(日) 14:23:18.13ID:8OOQa3AE
どっちも自分の脳内シチュでしか語ってないからふわっふわで論破出来るわけもなし
自分の主張が通る具体例上げるといいよ
0379デフォルトの名無しさん
垢版 |
2023/02/05(日) 14:35:53.55ID:LY0V54Tb
「カッコウのアルゴリズムさえまともに実装できてないからクソ遅いんだよな」
みたいに適当なワード混ぜて意味不明なこと言いつつ同意してる風を装うと「そうなんだよ!」とか勝手に乗っかってきて自爆するから面白いぞ
0381デフォルトの名無しさん
垢版 |
2023/02/05(日) 15:53:21.98ID:ANWYibFj
>>373
台所まで行けば箸(enum)があるのに手元のフォークで焼きそばを食べてる感じ
食べてるのがパスタ(Python)なら平気なんだけど
0383デフォルトの名無しさん
垢版 |
2023/02/05(日) 16:04:59.96ID:0ZBI/vwq
>>377
信頼するかどうかはあなた次第
>>359-360が嘘だらけだということが分からない人は基礎がなってないから勉強やり直すかパスタにするか
0385デフォルトの名無しさん
垢版 |
2023/02/05(日) 18:32:46.51ID:rtbv+KUs
>>381
凄い納得
enum使わずにanyhow使うような連中はPythonでも使っていろ
anyhowなんてものがあるから勘違いが起こる
0386デフォルトの名無しさん
垢版 |
2023/02/05(日) 20:10:29.95ID:QsKcw+fO
cargo crateのコード見てみた
anyhowを使ってエラーを上へ上げていく
enumを使っておらずエラーの網羅性はない
downcast_refを使ってエラー分岐している
0387デフォルトの名無しさん
垢版 |
2023/02/05(日) 20:38:51.85ID:1L9Nz43N
エラーなんて作成時点で未知のものが後から増えることもザラだし
何なら抽象レイヤー以下の実装の差し替え(ストレージのネットワーク化とか)で
動的に増えたりすることもあるんだから、網羅性とかすぐ成り立たなくなる。
可能なところで逃すものじゃないけど、こだわるものでもない。
0388デフォルトの名無しさん
垢版 |
2023/02/05(日) 21:15:55.10ID:yQ5U4c14
cargo みたいに手元や CI で実行するツールのエラー処理なんてその程度で十分ってこった。

もちろん、網羅が必要な領域のコードじゃそんなエラーハンドリングのやりかたじゃあ駄目だろうよ。
0389デフォルトの名無しさん
垢版 |
2023/02/05(日) 21:31:31.79ID:kVul7/Hf
多数の下部ライブラリから色んなエラーが上がってくるreqwestはそれらをdyn std::error::Errorへ入れているね
そしてdowncast_refで必要な分岐をして処理しているね
エラー処理はこれで十分でしょ
網羅しなくても残りは最終的にちゃんとエラー表示されるのだから
0390デフォルトの名無しさん
垢版 |
2023/02/05(日) 22:59:47.83ID:cfofmdL5
エラー処理で必須な網羅性とはenumの網羅性とは異なる
いつどこでどんなエラーが発生しても必ず処理されることがエラー処理の網羅性
つまりエラー処理されないまま通常処理に進まないことでありRustではResultの利用によりそれが保証されている
したがってdyn Errorを使って一部をダウンキャストによりエラー処理し残りをエラー表示処理でも網羅性を満たしている
0391デフォルトの名無しさん
垢版 |
2023/02/05(日) 23:51:35.27ID:BjcIBdbF
opaqueなerror typeを使うメリットは何なのか?デメリットは何なのか?
少なくともreqwestの開発者はそのトレードオフを検討した上で判断を下している

メリットもデメリットも理解できてないやつが珍説唱えても虚しいだけだぞ
0393デフォルトの名無しさん
垢版 |
2023/02/05(日) 23:58:58.86ID:QsKcw+fO
>>390
やっぱりそれでいいのか
Rustの標準IOライブラリはenumを使っているけどnon_exhaustive指定がしてありenumの網羅性チェックをむしろ使えないようにしてる
0394デフォルトの名無しさん
垢版 |
2023/02/06(月) 00:09:01.18ID:ZXNgtENY
>>390
一般的なエラー処理の網羅性はその解釈だな
Rustでは型システムと返り型Result及びResult放置をコンパイラが警告してくれるため必ず網羅される仕組み
0396デフォルトの名無しさん
垢版 |
2023/02/06(月) 06:52:59.94ID:OJBoAdFu
逆だよ
網羅性の扱いを禁止するために意図的にnon_exhaustive指定されている
そのようなエラーの種類には網羅性は必要がないだけでなく
今後もしエラーの種類が増えた場合に全網羅列挙して使用している既存のコードがエラーとなってしまう
そのためこういう時は不要である網羅性の扱いを禁止して全列挙コードを書かせないことで
今後エラーの種類が増えても既存の利用コードに影響を与えずに済む仕組み
0397デフォルトの名無しさん
垢版 |
2023/02/06(月) 12:30:43.08ID:wr+6RDlb
>>396
自信満々に間違った情報を中身のない文章で膨らませてもっともらしく見せようとするところがChatGPTそっくりww
0399デフォルトの名無しさん
垢版 |
2023/02/06(月) 14:14:21.50ID:C/yeK4bx
>>396で合っているけど補足すれば
全網羅列挙コードを書いてもコンパイラがそれを許さずエラーとなる
全網羅列挙しなくていいから必ず全マッチの _ => アームをコンパイラが要求してくる
つまりコンパイラによるエラーの網羅性チェックは不可能
0400デフォルトの名無しさん
垢版 |
2023/02/06(月) 21:51:09.46ID:MJNtWgHJ
そもそもRust以前に他のプログラミング言語でもそのようなエラーの種類の網羅が行なわれたことはない
IOエラーだけでも何十種類もあり列挙するだけでも大変で意味のない作業
エラー処理で必要とされる網羅性とはエラーの種類を全て列挙することではなく
>>390の説明が正しい
RustでResultを使えば保証される
0401デフォルトの名無しさん
垢版 |
2023/02/06(月) 21:59:33.19ID:T23InEdz
自分の書いたレスを正しい正しいと
一人で連呼してて虚しくならないのかな
0402デフォルトの名無しさん
垢版 |
2023/02/06(月) 22:26:04.02ID:7y0OcpN0
エラー処理の網羅性という話は元々
関数からエラー値が返って来る可能性があるのに見落として処理せずに続行しちゃったり
あるいは例外が返って来る可能性があるのに見落として処理しないままでいたり
そういう見落としがよく起きていたから
いつどこでどんなエラー(or例外)が起きても処理漏れがないようにプログラミングしましょうという話

もちろんRustではResultで返せばコンパイル時点でエラーや警告が出るためエラー処理の網羅性は満たされます
Resultを返していればdyn Errorやanyhowを使っていてももちろん大丈夫
そしてエラー処理の分岐にそれらのダウンキャストを使うのも何ら問題なし
0403デフォルトの名無しさん
垢版 |
2023/02/07(火) 02:02:21.05ID:smEuFI89
anyhow使ってて困ったことないので、これからもanyhow使いますね
0406デフォルトの名無しさん
垢版 |
2023/02/07(火) 10:30:33.69ID:jDwZWgRX
下手に分かったふりせず疑問をぶつけるパニック君のようなレスはスレにとっては有益
逆に知ったかぶりして嘘を撒き散らす某オジのレスは害しかない

一緒に仕事してても伸びるのは断然前者のタイプ
後者は多少知識があってもチームの足を引っ張る老害タイプ
0408デフォルトの名無しさん
垢版 |
2023/02/07(火) 12:39:13.84ID:GmLWJf7C
どの言語を使っていようがテスト設計とエラー処理設計は初心者と脱初心者を見分けるリトマス試験紙
チュートリアルやリファレンス読むだけでは身につかない
0411デフォルトの名無しさん
垢版 |
2023/02/07(火) 22:03:06.31ID:u8XyY9YO
今回のケースはRustのエラー処理を他の言語(C#あたり)の例外処理に寄せようとしてる感じ
「特定の例外クラスをcatchしたい」→「dyn Errorで投げてダウンキャストで分岐すればいい」みたいな
anyhowはそういう人のためにあるのかもしれない

オブジェクト指向言語専攻の人はRustのtraitを基底クラスの代わりに使いがちだよね
is-a継承はRustだとenumで表現できる場合が多いんだけど切り替えが難しいのかも
0413デフォルトの名無しさん
垢版 |
2023/02/07(火) 23:09:28.73ID:u8XyY9YO
それならいいんだけど型キャストしてまで分岐するとか言ってる人がいたから
自分で分岐する範囲くらいは自分で列挙しとけって話
0414デフォルトの名無しさん
垢版 |
2023/02/07(火) 23:53:31.04ID:23ICgzsB
下層から上がってくる99種類のエラーはログ吐かせるだけで、特別な処理したいエラーはひとつしかないのにいちいちenumに詰め直したりせんわな
0415デフォルトの名無しさん
垢版 |
2023/02/08(水) 00:04:28.76ID:mV68xos2

自分で分岐してエラー処理すんなら区別すべきエラーを決めるのは自分なのでanyhowやdyn Errorでダウンキャストしても問題ない

外から呼び出されるコードなら区別して処理するエラーを決めるのは呼び出し側なので区別できるようにenumで書く
0416デフォルトの名無しさん
垢版 |
2023/02/08(水) 00:35:28.79ID:ydIblX/+
すまんが、これってなんでダメなの?
ブロックの最後に式を書いてるのに、なんでreturnって書かないとリターンしないの???
そもそもエラーの内容に書いてあるmismatched typesって、一体何と何のタイプがミスマッチなんなんだ・・・・
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d1833710038ed821593015e5382de11f
エロい人教えて!!!
0417デフォルトの名無しさん
垢版 |
2023/02/08(水) 01:51:02.48ID:U3de6tMw
>>416
else句が無いのでifの条件式がfalseの場合はif-expressionは()になるけど
ifの条件式がtrueの場合はif-expressionがi32になるのでミスマッチ
0418デフォルトの名無しさん
垢版 |
2023/02/08(水) 01:59:22.59ID:W8WwzKcT
>>414
ログを吐かせるだけでもエラーによってログの吐き方を変えたいこともよくある話なのでケースバイケース
99種類を2種類に詰め直して片方をerased typeにしたりする
0419デフォルトの名無しさん
垢版 |
2023/02/08(水) 07:28:48.49ID:2c2bFNHO
上位の関数でもかなり多数のケースに分けてエラー処理する必要な場合だと
個別にenumにエラー型を収容する方が有利なケースもある
もちろんその場合でもanyhowやdyn Errorに収容してダウンキャストしてもよい
enum matchとダウンキャストの実行時コストはほぼ同じで優劣はなく視認性も変わらない
enumを使うとコードが増える問題はあるがあとは好みの問題
0420デフォルトの名無しさん
垢版 |
2023/02/08(水) 10:45:01.05ID:ENpYrX9l
ダウンキャストは下位モジュールに不必要に依存することになるので選択の余地があるなら基本的には使うべきではない

自crateで定義したエラー型にダウンキャストするくらいならエラーを定義するついでにenum書いとけばいいだけ
他crateで定義したエラー型にダウンキャストしてるとバージョンアップ時にサイレントにキャストが失敗して動作が変わる

あくまで非常口であって使わざるをえないときはマイナス面を理解した上で注意深く使うもの
0421デフォルトの名無しさん
垢版 |
2023/02/08(水) 10:52:13.58ID:fJPPomwd
UnknownErrorにわざわざ詰め直したログ吐くしかできない99種類あったエラーと1種類の自クレートのMyErrorをenumで2つ列挙して分岐するのと
MyErrorも含めて100種全部dynで上げてMyErrorだけダウンキャストすることの間に大した違いはない
0422デフォルトの名無しさん
垢版 |
2023/02/08(水) 12:29:34.73ID:/lg+THEr
アプリケーション開発とライブラリ開発の2つの視点があって、それぞれで戦略が違うというのが大元にあるからそこは理解してもらわないとね。
0424デフォルトの名無しさん
垢版 |
2023/02/08(水) 12:45:18.46ID:QfEWSkwW
両者で大きく異なるよね
ただし既出のcargoやreqwestなど違いに関わらずダウンキャストを使っているコードも多いから
どっちだと良くてどっちだとダメというものでもない気がする
0425デフォルトの名無しさん
垢版 |
2023/02/08(水) 12:48:39.58ID:QfEWSkwW
424は422へのレスね

>>423
そこはenum作って収容しようがdyn Errorに収容しようが関係なくpubじゃない型はどうにもならないような
0426デフォルトの名無しさん
垢版 |
2023/02/08(水) 13:05:56.18ID:B9DUhvwN
>>421
どういう種類の変更に対してコードのどの部分に手を入れる必要が出てくるのかを考えてみるといいよ
0427デフォルトの名無しさん
垢版 |
2023/02/08(水) 13:15:25.12ID:Fgr/3fzw
求められてもない具体性のない中身のない全く役に立たないアドバイスは有害でしかない
0428デフォルトの名無しさん
垢版 |
2023/02/08(水) 13:35:42.99ID:DnIJ53A+
現実にdowncast_ref()が使われているアプリやライブラリが多数あり
それらが問題になったことはないのだから
downcast_ref()を嫌っている人は思い込みで好き嫌いに過ぎないことを理解しようぜ
enumを作っても下位のエラー型を突っ込むだけでは何も変わらない
0430デフォルトの名無しさん
垢版 |
2023/02/08(水) 14:40:13.85ID:J3DHyZUt
前提条件付けて場合分けして考えろ
てかこんなことでスレの半分近くも消費すんな
0431デフォルトの名無しさん
垢版 |
2023/02/08(水) 16:15:41.93ID:ydIblX/+
>>417
そうだったのか!returnを書いたら通るのも、そうするとどちらも戻り値が()同士で統一されるってことか!
ありがとう!全然わかんなかったぜ!
0432デフォルトの名無しさん
垢版 |
2023/02/08(水) 16:16:54.39ID:VvFQM19K
>>417
>>416では無いが、そういう意味だったのか
単に厳し目にチェックしているからだと思っていた
0433デフォルトの名無しさん
垢版 |
2023/02/08(水) 17:13:58.11ID:e6ub/0SO
たぶんだけど「Rustでは値を返すのにreturnを省略できる」と誤解してるんじゃないかな
その誤解のためreturn bのreturnを省略してしまったと思われる

正しくは「Rustでは最後の値が返り値となる(のでreturnが不要)(だが使ってもよい)」
と「途中で返したい時はreturnを使う」

だから今回の例だと
if文の中では『途中だから』return bとbにreturnが必須
あるいは関数の最後をif-else式にしてしまえば『最後となるから』bにreturnは不要
0434デフォルトの名無しさん
垢版 |
2023/02/08(水) 17:28:24.72ID:e6ub/0SO
ちょっと誤解があるから追加
最後をif-else式にすれば全体に式returnのreturnが不要になる
そしてif-else式の中はreturnは不要というか付けない
そこにreturnを付けるとif-else式ではなぬif-else文になる
0442デフォルトの名無しさん
垢版 |
2023/02/09(木) 12:41:16.10ID:S7fEOBGh
わざわざ早期リターンのために?演算子なんて用意してるRustで早期リターン禁止とな?!
0444デフォルトの名無しさん
垢版 |
2023/02/09(木) 13:10:12.86ID:wPt4Q+MY
なんで昔は早期returnがバグにつながると考えられてたの?
どう考えても早期returnしない方がバグにつながりやすいと思うんだが
0445デフォルトの名無しさん
垢版 |
2023/02/09(木) 14:20:08.85ID:QqGr+Vdk
もっと昔にgotoの使いすぎで制御構造がぐちゃぐちゃになったことへの反動で
複雑な制御構造は使わないようにしよう、という流れだったかと
0446デフォルトの名無しさん
垢版 |
2023/02/09(木) 14:55:47.47ID:UhaInviD
>>444
C言語時代の話な
例えばこういうパターンでメモリーリークしたりするバグがたくさんあった

f(...){
p = malloc(...);
...
if(...) return;
...
free(p);
}
0447デフォルトの名無しさん
垢版 |
2023/02/09(木) 15:21:57.59ID:9WtqRr2n
そのあたりも自動メモリ開放のRustなら大丈夫だね
if文で早期return/continue/breakしないと、どんどんifネストが深くなっていくのでそれを避けたい
0448デフォルトの名無しさん
垢版 |
2023/02/09(木) 15:37:28.09ID:Ktnp537B
>>446
リソース確保・解放するレイヤーとそれを使って処理を行うレイヤーを分ければよくない?

f(...){
p = malloc(...);
g(p, …);
free(p);
}

g(…) {
...
if(...) return;
...
}

ifのネストが浅くなっても逆に関数のネストが深くなりすぎて読みにくくなる側面があるということなのかな?
0449デフォルトの名無しさん
垢版 |
2023/02/09(木) 15:51:48.67ID:oQtbOpVY
>>448
分けましょうってルール化したくらいで完璧に守られるなら誰も苦労しないんだよな…
そのうち処理レイヤー側でmallocするやつが出てくるやつ
0451デフォルトの名無しさん
垢版 |
2023/02/09(木) 16:04:18.76ID:1694Wm1I
ifがネスとしていたりした場合に、returnみたいにif-expressionの方に結果を返したい時ってどうすればいいの?
0455デフォルトの名無しさん
垢版 |
2023/02/09(木) 16:36:32.32ID:8ktpZl0b
言語仕様的に可能でも規則で縛ることで安全を担保しようという方法は
いずれ失敗するからそういう要素は必ず言語側の仕様で保証すべき、というのがRustの思想なんだから
「あれは危険だから駄目、コーディング規則で縛る」という発想自体が間違ってる
0456デフォルトの名無しさん
垢版 |
2023/02/09(木) 16:43:33.27ID:UhaInviD
>>448
リソースが1つだけならいいかも知れないけど複数リソースが絡んでたりすると色々ややこしいコードになっちゃう
>>452
コードレビュー時に return 検索したら
0459デフォルトの名無しさん
垢版 |
2023/02/09(木) 16:49:18.29ID:9WtqRr2n
こういうやつ?
let result = 'found: {
 for i in 0..100 {
  if f(i) {
   break 'found Some(i);
  }
 }
 None
};
0460デフォルトの名無しさん
垢版 |
2023/02/09(木) 17:15:30.09ID:1694Wm1I
>>453-454
>>459
やりたかったのこれだ、せんきゅー!
0462はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/09(木) 17:43:07.29ID:zt0qN6wf
>>444
構造化が重要視された時代がある。
順次・反復・分岐によって処理の流れを構築するという点から見ると
早期リターンは流れをすっとばして大ジャンプしてることになるので
コードを追うのを難しくすると考えられていた。
「出入口はひとつずつ」は基本思想だったんだよ。
構造化が不十分だった時代にまず構造化することが大事だったという話。

今では構造化が当たり前になったから次の段階として順次・反復・分岐という構造だけでは
上手く扱いづらい部分をどうやるのがいいのかという模索が続いてるわけ。
0463デフォルトの名無しさん
垢版 |
2023/02/09(木) 18:03:17.12ID:9WtqRr2n
戻るgotoは結局なんらかのループを表しているので
Rustならラベル付loopに指定continueで表せる
進むgotoは無制限ではなくラベル指定breakの大域脱出型に制限される
という認識で合ってる?
0464デフォルトの名無しさん
垢版 |
2023/02/09(木) 18:18:38.11ID:xZSrodqJ
>>454
なんか微妙な機能だな
関数化して早期returnさせる手間が嫌ということなんだろうけどそれなら||や&&オペレータをOptionやResult用に上書きできるようにした方がずっと使いやすい
tryブロックとの非対称性も気になる
0465デフォルトの名無しさん
垢版 |
2023/02/09(木) 18:30:28.03ID:9WtqRr2n
>>464
今までに既にあった機能のラベル付loop式のラベル指定breakという使われ方のうち
ループしない使われ方が多かったため事実上のシンタックスシュガーが導入されただけだよ
だから微妙な機能が追加されたという見方は正しくない
0466デフォルトの名無しさん
垢版 |
2023/02/09(木) 18:30:33.67ID:QonGkYb5
>>464
ほとんどの場合はこんなん使う前にその部分を関数に切り出すことを考えるべきというのはめちゃくちゃ言われてる
awaitとかResultとかライフタイムとかいろいろ絡んできたときに再利用もされない数行の処理のために長々と型を書かなくても済むのがユースケースのひとつと思われる
0468デフォルトの名無しさん
垢版 |
2023/02/09(木) 18:50:34.43ID:hFEBZw9k
どうせなら仮変数みたいな変数割当機能も用意して、末尾最適化再帰風ループもできるようにならないかね。
0469デフォルトの名無しさん
垢版 |
2023/02/09(木) 18:53:10.62ID:9WtqRr2n
>>467
既に昔から存在していたloop式を
loopと書かなくてもよくなっただけだよ
今までは皆はloop式の最後をbreakすることでloopさせずにこの同じ機能を使っていた
今回でloopを省けるようになったため最後のbreakが不要とだけにすぎない
今さら文句をつけるのが不思議
0470デフォルトの名無しさん
垢版 |
2023/02/09(木) 19:02:26.27ID:o9a7e9s5
早期returnってファウラーのガード節の話じゃないん?
あの使い方する限り安全安心可読性改良にしかならないよな?
0473デフォルトの名無しさん
垢版 |
2023/02/09(木) 19:15:02.58ID:9WtqRr2n
if letでネストが深くならないように早期return等しようとすると無駄コードが膨らんでいた問題も
同時に導入されたlet elseによって解決されたね
0476デフォルトの名無しさん
垢版 |
2023/02/09(木) 19:40:55.17ID:rpwFU8e5
ルールの背景を考えずに破ろうとするやつも多いけどな。

守破離は基本だろ。ブルースリーのパンチキックの逸話でもいいけど。
0477デフォルトの名無しさん
垢版 |
2023/02/09(木) 19:47:18.19ID:Kxe1JjXm
>>476
合理的なロジックがないという点で同類じゃね
「ルールだから問題ない(思考停止)」で他人に迷惑をかけるのも同じ
そして多くの場合無責任までセットだ
0478デフォルトの名無しさん
垢版 |
2023/02/09(木) 19:54:21.56ID:bVNNfLSa
そもそも失敗できなくするのがここ10年ぐらいのトレンドだろ。
だから静的型やRustが支持されるわけで。
0479デフォルトの名無しさん
垢版 |
2023/02/09(木) 20:07:33.02ID:rpwFU8e5
>>477
ルールについては「決定と実行の分離」という重要な側面があるよ。

頭のいい奴がルールを作れば、アホがルール通りに実行しても被害は少ない。アホがルールを破るよりよほどマシ。
0480デフォルトの名無しさん
垢版 |
2023/02/09(木) 20:20:31.75ID:9WtqRr2n
Rustの制御構文としては
昨年末の2つの追加で
従来は不便で需要が多かった形が無事に解決したから一段落かな
0483デフォルトの名無しさん
垢版 |
2023/02/09(木) 23:06:57.24ID:QonGkYb5

何らかの目的で大域脱出を用意すると必ず妙ちくりんな悪用を考える奴が出てくるんだよな
0484はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/09(木) 23:22:20.06ID:zt0qN6wf
そういえばコンテナのイテレーションの順序が未規定なときに
順序に依存したコードを書かないように乱数でわざとデタラメな順序にしたら
乱数生成器として使うやつが出てきたって話があったな。

どんな機能も下手に使ったら無茶苦茶にしうるってのはもうどうしようもなくない?
0485デフォルトの名無しさん
垢版 |
2023/02/09(木) 23:42:25.26ID:iUuqvbE0
>>56のが実現したらRFCの例は||で代替可
let result = (first_container.iter().find(|&&v| v > 0)
|| second_container.iter().find(|&&v| v < 0))
.unwrap_or(&0);

labelやbreakの手続き的なやり方よりこっちの方が汎用性も高いしrustの目指すべき方向に合ってると思う
0486デフォルトの名無しさん
垢版 |
2023/02/10(金) 01:49:50.47ID:JoKDyp+E
メソッド抽出は嫌
クロージャの即時実行も嫌
ラベル付きbreakならOK!
って感覚が俺には理解できんが
ニーズがあるならいいんじゃね
0487デフォルトの名無しさん
垢版 |
2023/02/10(金) 02:22:12.82ID:KiCBMwJT
>>486
関数切り出しやIIFEだと式の値はResult型になるようなところで、
ラベル付きブロックだとエラーまわりは親の関数に完全に任せて該当の式の値を生で返せる
0489デフォルトの名無しさん
垢版 |
2023/02/10(金) 03:36:08.11ID:eoPLVAGF
>>487
?オペレータ使えばいいだけなんだが?
逆にエラーまわりだけ親関数に任せるとかヤバくね?
0490デフォルトの名無しさん
垢版 |
2023/02/10(金) 06:59:25.26ID:Fpp4vOr0
>>488
ラベルでジャンプしていない
loop式の構文のloop抜きと動作も概念も全く同じだから
今回Rustはたまたま同じ構文を採用しただけ

例えば>>459の例は
ラベルを用いない別の新たな構文{{…}}を導入すればこうなる
let result = {{
 for i in 0..100 {
  if f(i) {
   return Some(i);
  }
 }
 None
}};
動作も意味も全く同じであり
ラベルにジャンプしていないことが理解できるだろう
0491デフォルトの名無しさん
垢版 |
2023/02/10(金) 07:32:00.75ID:Fpp4vOr0
そしてRustがなぜ今回の構文の形を採用したか
・returnでもbreakでも多重になった時にどれを終えるのか曖昧になるため何らかの指定は必要
・ラベルによる指定はRustの他の構文でも共通に既に使われており親和性がある
・returnの使用は混乱を防ぐために関数とクロージャーから返る位置付けのみに保ちたい
・既存のloop式と今回の構文はloopキーワードを除けば全く同じであり導入前はloop式で代替されていた
0492デフォルトの名無しさん
垢版 |
2023/02/10(金) 07:54:41.21ID:Fpp4vOr0
>>488
必要性に応じて関数として切り出すのも構わない
そして関数として分離した方が好ましい場合もあるだろう
しかし常に関数切り出しを強いられる言語だったとしたら煩雑すぎて機能不足と言えるから使い分けできることが必要
0494デフォルトの名無しさん
垢版 |
2023/02/10(金) 08:18:49.59ID:Fpp4vOr0
>>493
従来からforやloop式で使われてきた早期return(離脱)つまりRustでのラベル指定break
そして今回Rust導入されたブロック式での早期return(離脱)つまり同様に構文としてはラベル指定break
それらに対して「ラベルでジャンプ」とは何を言いたいのか?
0496デフォルトの名無しさん
垢版 |
2023/02/10(金) 08:39:40.06ID:Fpp4vOr0
>>495
遅延評価orの型が
現在はbool型のみに制限されているから
それをOption型などにも使えるようにしよう!という話じゃないかな
0497デフォルトの名無しさん
垢版 |
2023/02/10(金) 08:41:20.86ID:KiCBMwJT
>>489
関数に切り出した時点で「その範囲のResultの型」を考慮しなくちゃいけなくなるから?演算子では何も解決してないし、
切り出さなきゃ元からその関数の処理だから何もやばくないぞ
0498デフォルトの名無しさん
垢版 |
2023/02/10(金) 08:50:58.78ID:Fpp4vOr0
関数切り出しすると
その中でも継続して使う変数(値)を参照として全て渡してそれらの型宣言も改めて行なってと煩雑さとコードの重複が大きい
もちろん返り値型も型推論で済まなくなり明確に宣言しなければならなくなる

したがって関数切り出しの方が明確にメリットが上回るケースを除いて
適材適所でブロック式で済ませられるようになった今回の導入は大きな意義があると思う
0500デフォルトの名無しさん
垢版 |
2023/02/10(金) 09:39:52.23ID:FTCkglUc
>>490
動作も意味も全く同じとのことだが
その構文でネストしたブロックから抜けられるのかい?
0502デフォルトの名無しさん
垢版 |
2023/02/10(金) 09:58:49.88ID:zTpuYOFQ
5年もの歳月を費やしてstabilizeするほど意味ある機能じゃないよな
超ニッチなnice to haveなんだからこんな機能実装するくらいなら他の作業してくれよ
0503デフォルトの名無しさん
垢版 |
2023/02/10(金) 09:58:58.37ID:f/xkkyji
>>499
Rustで関数のネスト定義は可能だけどスコープを親関数内に限定するだけだよね
親関数の変数をもちろん操作できないので改めて引数も戻り値も全て型宣言して受け渡ししなければならない
0504デフォルトの名無しさん
垢版 |
2023/02/10(金) 10:00:29.07ID:76BGvvFm
>>499
関数のネストでやるためには
関数に切り出す必要があるから同じことを言ってるんじゃない?
0505デフォルトの名無しさん
垢版 |
2023/02/10(金) 10:06:08.19ID:f/xkkyji
>>500
forやloopを使ったときにどのbreakか区別できるようにラベルが付いてるだけでラベル付ブロック式のネストまでは元々求められていないんじゃないかな
たまたまラベル付となったからネストさせて指定して抜けることも可能なのかも知れないけどさ
0506デフォルトの名無しさん
垢版 |
2023/02/10(金) 11:35:14.97ID:D7CjmUqS
>>505
指定したラベル位置に制御を移すような動きのことを一般的にはジャンプと呼ぶ
ラベルで指定したブロックを”抜ける”と呼ぶ感覚ももちろん理解できるが同じようにジャンプと呼ぶ感覚くらいは理解してやれって話
0507デフォルトの名無しさん
垢版 |
2023/02/10(金) 12:14:15.40ID:53cyCMdn
>>502
ブロック式の早期離脱機能は同時に導入されたlet elseと並んでRustにとって必須の機能
これまではブロック式で早期離脱が出来なかったため代替処置として
・ブロックの代わりにわざわざクロージャを用意して即時実行する
・ループさせないのにloop式を目的外でブロック式として用いる
・関数として切り出して引数型や戻り型などコードが無駄に膨らむ
以上3通りの方法が苦しい回避処置として取られてきた
この問題が一気に解決した
0508デフォルトの名無しさん
垢版 |
2023/02/10(金) 13:14:46.92ID:OY+cHUF0
>>507
おまえホント壊れたレコードみたいだな
馬鹿の一つ覚えで繰り返し同じことしか言えないからおまえが出しゃばってくるとすぐスレが腐る
0509デフォルトの名無しさん
垢版 |
2023/02/10(金) 13:40:49.41ID:icbsua9B
オジさんは即時実行マンセー派だったのに宗旨替えしたのかw
と言っても忌み嫌われてた即時実行から半歩前進して半歩後退してるみたいなので実質進歩してないな
0511デフォルトの名無しさん
垢版 |
2023/02/10(金) 15:10:52.96ID:p1oXUla5
誰もが必ず使うエラーまわりには散々ボイラープレートを要求するくせに
ブロックからの早期returnが必要なくらいの処理を関数に切り出したくないという理由だけで
プチgoto入れちゃうのはバランス感覚おかしいわな
0512デフォルトの名無しさん
垢版 |
2023/02/10(金) 15:25:57.81ID:EzUIw58a
ブロック式も関数も複数の文をひとつの式にするものだから関数から早期returnできるならブロック式から早期breakできてもええやん😁
0513デフォルトの名無しさん
垢版 |
2023/02/10(金) 16:46:17.45ID:ec863R6+
returnやbreakのことをgoto扱いしてる人は頭おかしい
むしろgotoを排除するために現在の言語ほとんどに備えられている
ラベル付breakをサポートする言語も多い
0515デフォルトの名無しさん
垢版 |
2023/02/10(金) 17:37:10.71ID:gd5eXGUi
Rustの機能はすべて素晴らしいということにしないと気が済まない人がいるのはよく分かった
0517デフォルトの名無しさん
垢版 |
2023/02/10(金) 18:07:23.86ID:VmkjxzjW
Rust の機能が全て優れてるとは思わないけど ラベル付き break なんて揉めるような機能じゃないだろ...
0519デフォルトの名無しさん
垢版 |
2023/02/10(金) 19:02:21.11ID:MJOsdNRe
ブロックからの脱出とジャンプを同列に考えるやつは勉強不足だと思うがね。

Rustのスタックフレーム志向とかを考えれば、ブロック出入り操作を重視するのは自然。逆にスタックフレームの局所性を破壊する例外フローとかジャンプは嫌われて当然だわ。
例外フローにおけるエスケープ解析て確立しているんだっけ?
0524デフォルトの名無しさん
垢版 |
2023/02/10(金) 19:24:57.65ID:VelAUwkm
>>520
Rustには何年も前からラベル付breakがあります
今さら文句をつけている人はRustを知らずイチャモンを付けたいだけだとバレていますよ

メジャーなプログラミング言語の大半がラベル付breakを備えています
JavaでもSwiftにもGoもJavaScriptすらラベル付breakを持っています
プログラミングにおいて必須の機能だからです

逆にラベル付breakを持っていない代表的な言語がC/C++です
今回のRust叩きをしている犯人はいつもと同じ人だと分かります
0525デフォルトの名無しさん
垢版 |
2023/02/10(金) 19:52:12.29ID:ec863R6+
breakに対してジャンプだとかgotoだとかトンデモ発言が出ていたのはそういうことか
C/C++しか知らないと多重ループすらgotoで抜けるしかないもんな
そういう貧弱な世界しか知らない視野の狭い人だから必死にRustを叩いていたわけか
0526デフォルトの名無しさん
垢版 |
2023/02/10(金) 21:33:52.77ID:zr0HQZhu
前から常駐してるアンチRustのやつだろ
ばればれだがアンチとばれないように装いつつRustの色んな点を批判してきた
特にRustならではの機能とか新たな機能とかRustらしい書き方とかを嫌う
0528デフォルトの名無しさん
垢版 |
2023/02/10(金) 22:59:03.20ID:Y2H2O9Fe
>>524
大半の言語が備えてるラベル付breakはループから抜けるものでブロックから抜けるものじゃないぞ
0529デフォルトの名無しさん
垢版 |
2023/02/10(金) 23:14:34.63ID:z32i1LMi
swiftがdo statementでブロックスコープから抜ける機能を用意してるがtry/catchなしの形では誰も使ってない
0530デフォルトの名無しさん
垢版 |
2023/02/10(金) 23:16:17.28ID:TiW7YUw7
そんなことよりさっさとif let Some(c) = chars.next(); c.is_whitespace() {とかって書けるようになってほしい
0531デフォルトの名無しさん
垢版 |
2023/02/10(金) 23:22:50.62ID:KiCBMwJT
ブロックは「必ず1回で終了するループ」と解釈可能なのでループからのラベル指定breakがあるならブロックからもbreakで抜けられる方が自然
0532デフォルトの名無しさん
垢版 |
2023/02/10(金) 23:24:33.98ID:PcQ6rbEj
Javaも文法的にはループ以外でもラベル付きブレイク使えるけど絶対使わないな
0534デフォルトの名無しさん
垢版 |
2023/02/10(金) 23:37:03.68ID:q3LdPEQ+
RFCの例を4パターンで書いてみたけどラベル付きbreakは無いな
1か2のパターンに収まる形にリファクタリングする
大半の人がラベル付きbreakを選びたくなるようなサンプルはないのかな?

1. 関数化
2. Optionコンビネータ
3. クロージャ
4. ラベル付きbreak

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e365b15243be65f5fc2d09a94324317e
0535デフォルトの名無しさん
垢版 |
2023/02/10(金) 23:46:57.14ID:XHs/nBWT
流れと一切関係ないけど
rubyは一時期tapとbreakで値を返す文化?あったな
foo.tap {|x| bar} // selfつまりfooを返す
foo.tap {|x| break bar} // breakでbarを返す
foo.then {|x| bar} // ブロックの結果つまりbarを返す。今はthen使うのが素直。
0538デフォルトの名無しさん
垢版 |
2023/02/11(土) 00:29:21.70ID:N8U5Q6xc
異なる種類のエラーを返す関数が絡んできたとき、ラベル指定breakのみエラーの合成を?演算子で関数境界に押し込められる
関数やクロージャだと「ブロック内のエラーを合成した型」を明示的に取り扱うことになって二度手間
0539デフォルトの名無しさん
垢版 |
2023/02/11(土) 00:48:21.15ID:C7Sk8k8l
>>535
tapでbreakなんて初めて知ったわ
イテレータのメソッドチェーンの途中経過を出力する時にしか使ったことなかった
0541デフォルトの名無しさん
垢版 |
2023/02/11(土) 01:49:22.40ID:sVZS7q05
すまんがRustlingsでまたちょっと教えてほしいんだけどさ
これ↓のListing 8-8の&mutって、一体どういう意味があるの???
https://doc.rust-lang.org/book/ch08-01-vectors.html
Rustlingsをやっていて、似たような場面で&mutなしでも動いちゃうように見えるけど・・・・状況が似て非なるものなんだろか・・・・・
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b4a253142ce1e394ba13bb0c2fc58f11
0542デフォルトの名無しさん
垢版 |
2023/02/11(土) 02:18:23.31ID:N8U5Q6xc
>>541
詳細はトレイトとか Deref とか IntoIterator とか関連型とかその章ではまだ出て来てない概念が色々絡むが

for item in v の v に対して
Vec<T> を渡したら item は T になって所有権ごと持ってく
&Vec<T> を渡したら item は &T になって不変参照のイテレーションになる
&mut Vec<T> を渡したら item は &mut T になって可変参照のイテレーションになる


Vec<T>は DerefMut<Target=[T]> を実装しているから &mut Vec<T> は暗黙のうちに deref_mut のメソッドを通して &mut [T] に変換されて
その &mut [T] が IntoIterator<Item=&mut T> を実装しているからfor文で &mut T のイテレーションができる
0543デフォルトの名無しさん
垢版 |
2023/02/11(土) 03:08:28.64ID:ClzSOMcn
>>534
その程度ならば型宣言で冗長になる関数化をするまでもないからブロック式でも十分かな
使い分けできるようにブロック式の不備を整備したRustの方針は正しいと思うよ

>>541
所有権を渡すのは消費尽くすときだけでその後も使いたい時は参照&か可変参照&mutを渡す
そのコードのv.iter_mut()の方に見かけ上&mutが見当たらないのはメソッド定義にそれがあるから
メソッドでは所有権を渡すか参照を渡すか可変参照を渡すかをその定義でselfか&selfか&mut selfか指定することでメソッド使用時に毎回指定しなくて済むようになっている
0544デフォルトの名無しさん
垢版 |
2023/02/11(土) 03:56:21.21ID:VRz38Asr
>>541
vがVec<T>の場合
for i in &mut v {…} と
for i in v.iter_mut() {…} は同じ

前者は&mut Vec<T>のIntoIteratorトレイトのinto_iter()が呼ばれる
その中身はself.iter_mut()なので後者と同じになる

for loopはiterable(IntoIteratorを実装してるもの)を受け取って
そのinto_iter()を呼び出してからイテレートする仕組み
https://doc.rust-lang.org/std/iter/index.html#for-loops-and-intoiterator
0545デフォルトの名無しさん
垢版 |
2023/02/11(土) 15:27:39.27ID:VRz38Asr
>>542
>&mut Vec<T> は暗黙のうちに deref_mut のメソッドを通して &mut [T] に変換されて

細かいけどここちょっと気になった
for loopに渡されたタイミングでDeref Coercionが発生するんじゃなくて
まず最初に渡された値の型でIntoIterator::into_iterが呼ばれて
その中のself.iter_mutのようなメソッド呼び出し時にVecに該当メソッドがないから
Deref Coercionが発生してslice::iter_mutが呼ばれるという処理順だと思う
0547デフォルトの名無しさん
垢版 |
2023/02/11(土) 18:03:53.39ID:RzhQX/na
なるほど
処理名をラベル名として付与するとラベル付ブロックが非常にわかりやすくなった
関数化と異なり無駄な引数宣言と型宣言が不要となり可読性が増した
もちろん関数化した方が適してる場合もあるだろうから上手く使い分けると良さそう
0548デフォルトの名無しさん
垢版 |
2023/02/11(土) 18:29:02.74ID:vxEXQ/Iw
さすが汚コーダー!
可読性や保守性になんて目もくれない!
保守なんてやらないもの!
0549デフォルトの名無しさん
垢版 |
2023/02/11(土) 18:55:39.54ID:o3GDXEGy
>>516
それな!(Noneでこんな感じにしちゃったんだろう、コール側がこうである必然性があまりない);
0551デフォルトの名無しさん
垢版 |
2023/02/11(土) 20:39:00.98ID:PvIfa6j8
外側の関数で既に変数定義してるのに、再び内側の関数の引数で宣言するのが二度手間だったから、ブロック化いいかも。
特に参照している変数が多いと連れ回しと、型宣言が大変だった。
0556デフォルトの名無しさん
垢版 |
2023/02/11(土) 21:20:48.03ID:8c0BE6VG
try_blocksが安定化されればここまでの話全部吹っ飛ぶんだけど
それまでのつなぎでしかないコードでここまで議論を紛糾させる必要なんてないのよ
0560デフォルトの名無しさん
垢版 |
2023/02/11(土) 22:18:32.89ID:N8U5Q6xc
>>556
try ブロックとラベル指定ブロックて用途違うんじゃね

let result = 'found: {
 for i in 0..100 {
  if f(i) {
   break 'found foo(i)?;
  }
 }
 bar()?;
};
0562デフォルトの名無しさん
垢版 |
2023/02/11(土) 22:23:01.29ID:N8U5Q6xc
途中送信
>>560 のケースで
foo(i) が Result<i32, FooError>
bar() が Result<i32, BarError>
を返すとして、ここでFooErrorとBarErrorの合成を考えなくても関数境界にエラー合成を押し付けて、
result の型を i32 にできるのがラベル付きブロック

クロージャとかは?演算子のスコープを作ってしまうので一旦Resultの型を明示しなきゃいけなくて、
FooErrorとBarErrorの合成をロジックの途中に挟むことになってうれしくない
0564デフォルトの名無しさん
垢版 |
2023/02/11(土) 23:15:54.51ID:PvIfa6j8
>>556
それはエラーの早期離脱のためだから、普通の値の早期離脱には使えない。
break可能なブロックは必要でしょう。
0565デフォルトの名無しさん
垢版 |
2023/02/11(土) 23:32:14.59ID:PvIfa6j8
>>562
従来のif式やmatch式と同様に、tryでないblock式では?を通過してくれるところが嬉しいポイントかな。
一方でtry block式はTry実装のResult型などになってしまい別物。
0567デフォルトの名無しさん
垢版 |
2023/02/12(日) 00:46:15.75ID:iluQvMBc
>>566
その人じゃないけど
tryとの違いを示してる簡素な例にその反論は意味ない
そして多重forの一般形となるだけでそのやり方は破綻
0569デフォルトの名無しさん
垢版 |
2023/02/12(日) 00:56:29.87ID:MRyWK0X4
破綻するかどうかは別として
多重forの中で種類の異なるエラーを返すような処理を直接書くことにはすごく疑問を感じるから
本当にそういうやり方が必要な状況があるなら見てみたいね
0571デフォルトの名無しさん
垢版 |
2023/02/12(日) 01:45:15.49ID:iluQvMBc
単なる多重forショートカットの話だよ
とりあえずエラーや可変長や可変参照問題は抜きにシンプルで
let n = 'calc: {
 for i in 0..100 {
  if f(i) {
   break 'calc ff(i);
  }
  for j in 0..100 {
   if g(i, j) {
    break 'calc gg(i, j);
   }
  }
 }
 0
};
0572デフォルトの名無しさん
垢版 |
2023/02/12(日) 02:21:27.18ID:mvDk5H0/
ラベル付きブロック式は特に新しい挙動は導入していない
早期脱出と?のエスカレーションの併用が可能になっただけ

関数:
〇変数、ライフタイムのスコープ
×環境のキャプチャ
〇早期脱出
×?演算子のエスカレーション

クロージャ
〇変数、ライフタイムのスコープ
〇環境のキャプチャ
〇早期脱出
×?演算子のエスカレーション

無名ブロック式:
〇変数、ライフタイムのスコープ
〇環境のキャプチャ
×早期脱出
〇?演算子のエスカレーション

ラベル付きブロック式:
〇変数、ライフタイムのスコープ
〇環境のキャプチャ
〇早期脱出
〇?演算子のエスカレーション
0573デフォルトの名無しさん
垢版 |
2023/02/12(日) 02:33:03.96ID:277pKKEQ
>>571
?使わないならクロージャでいいパターンでは?
あとそろそろfやggじゃ抽象的すぎてきついから実戦で使いそうなパターンの例を頼むわ
0576デフォルトの名無しさん
垢版 |
2023/02/12(日) 03:00:29.86ID:iluQvMBc
>>573
クロージャ即時実行だとできないこともある

>>575
なるほど
引用

>ラベル付きブレークはループ構造にすでに存在していたため、これは独自の新機能ではなく、既存の機能の一般化でした。
>さらに、クロージャは、ネストして外側のクロージャからブレークしたり、包含関数から戻ったりすることができないため、ラベル付きブレークほど強力ではありません。
>いずれにせよ、この機能は安定しており、削除されることはありません。
0579デフォルトの名無しさん
垢版 |
2023/02/12(日) 11:36:01.27ID:mvDk5H0/
機能的な差異(できることの違い)を示すためのサンプルコードにアンチパターンがどうのとか一生言ってる奴はこの世のすべてのコードから大域脱出を排除してきて
0581はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/12(日) 11:47:23.89ID:b/cm1PRG
大域脱出自体がアンチパターンではあるが
それでも必要になったときのために比較的マシな方法があったほうがよいというのは両立する話なんだよな。
0582デフォルトの名無しさん
垢版 |
2023/02/12(日) 11:51:17.64ID:VpAOtCID
短絡評価の&&と||がResultやOptionで使えるようになればtryブロックはともかくlabeled breakは使われなくなるよ
0583デフォルトの名無しさん
垢版 |
2023/02/12(日) 12:02:26.70ID:UeaSFBcM
短絡でブロック式がすべて死滅するとは思えないからラベル指定breakも死滅しないだろうな
ブロック式が途中で抜けられるようになっただけなんだし、ブロック式書いてて途中で式の値を確定したくなったらラベル指定breakの出番
0585デフォルトの名無しさん
垢版 |
2023/02/12(日) 12:09:09.65ID:KAxOFwBs
50行や100行を超えるような関数を書いても何も感じない流派の人と
10行以下でもリファクタリングの要否を検討するような流派の人とでは
審美眼というか根本的な価値観が違うから
お互いスタンスの違いを認識しないと話が噛み合わないよ
0586デフォルトの名無しさん
垢版 |
2023/02/12(日) 12:17:07.80ID:mvDk5H0/
数ヵ月前にstabledに入ってる機能とRFCすらマージされてないプロポーザルを比較するのって
捕らぬ狸の皮算用って奴じゃないですかね
0587デフォルトの名無しさん
垢版 |
2023/02/12(日) 12:18:39.30ID:wxFdc7Z6
>>581
例えば>>571って大域脱出なのか?
無駄なループを回らないために早期離脱しているだけに見える
それがアンチパターンだと主張するならばどうやって無駄なループを回避するんだ?
0588デフォルトの名無しさん
垢版 |
2023/02/12(日) 12:25:29.24ID:haDD5+eS
>>580
let ij = (0..100)
.cartesian_product(-1..100)
.find(|&(i, j)| if j == -1 { f(i) } else { g(i, j) });
match ij {
Some((i, -1)) => ff(i),
Some((i, j)) => gg(i, j),
_ => 0,
}

結局やってることはfindして結果に関数適用してるだけだよね
0590デフォルトの名無しさん
垢版 |
2023/02/12(日) 12:46:08.97ID:Im2qSh0/
>>588
それ動くけど
イテレータをi依存にされたり
判定方法を変えられたらすぐに破綻しちゃうな
さらに可読性がない上に保守性もない
そのコードは失格
0591デフォルトの名無しさん
垢版 |
2023/02/12(日) 12:48:00.42ID:3RfSmBLj
他の書き方があるって主張は不要論になってないんだよな
ラベルbreakってシンタックスシュガーでしかないから
もともと実現方法があるのは当然

ある処理においてよりシンプルで学習コストが低い記法があれば
その処理では不要と言える
0593デフォルトの名無しさん
垢版 |
2023/02/12(日) 12:52:28.45ID:mvDk5H0/
>>590
判定方法変わらなくても>>592で終了

自然数しか出てこないコードに突然勝手に負数を導入し出すあたりJS畑から来たのかな
0594はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/12(日) 12:56:01.59ID:b/cm1PRG
>>587
・ パターンとして分類するとアンチパターンの範疇に入る
・ しかし必要な場面もある (からマシな方法としてラベル付きブレークが導入された)
0595デフォルトの名無しさん
垢版 |
2023/02/12(日) 13:07:40.20ID:g76UXZf8
適材適所を無視して何でもイテレータメソッドチェーンにしようとする人たちはたまにいるけど
多重ループで条件により早期で抜けたり何段かまとめて抜けたりする時は>>571のように素直に多重forまたはloopが分かりやすい
loop式だとそれ自体もbreakで値を返せるようになるがどの段のloopを抜けるかでラベル指定breakは今までも使われてきた
だからラベル付きブロック式にも違和感ないが拒否反応を示してる人は技術的ではなく感情的になっているだけではないかと思われる
0596デフォルトの名無しさん
垢版 |
2023/02/12(日) 13:13:11.85ID:g76UXZf8
>>594
多重ループを早期で抜けるのがアンチパターンとは聞いたことがない
最近の多くの言語が持っているラベル付きbreakがC/C++は持っていないため多段抜けが出来なくてやむを得ずに状態変数管理することはあるが
それはC/C++言語の制約であり言語仕様が弱いだけなのでそこでの習慣に引っ張られてはいけない
0599デフォルトの名無しさん
垢版 |
2023/02/12(日) 14:40:41.70ID:FQ3NjXFA
>>585
どちらかというと
What中心でコードを構成する人と
How中心でコードを構成する人の考え方の違いじゃないか?
0600はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/12(日) 14:52:22.89ID:b/cm1PRG
>>596
私が >>581 で述べている「両立する」ってところを無視しないでくれ。
(形式としては) 多重ループからの脱出が大域脱出でありアンチパターンであることと
ラベル付きブレークが (回りくどいフラグ管理や goto より) マシな解決方法であるというのは両立すると言ってるんだ。
0601デフォルトの名無しさん
垢版 |
2023/02/12(日) 15:03:13.37ID:g76UXZf8
>>600
代替策を示さずにアンチパターンだと唱えるのをそろそろ辞めにしよう
多重ループから脱出しないコードを示してくれ
0602はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/12(日) 15:09:50.74ID:b/cm1PRG
>>601
「形式として」と念押ししてるんだから実態はそうではないというニュアンスを読み取ってくれ。
0603デフォルトの名無しさん
垢版 |
2023/02/12(日) 15:11:42.38ID:9lLsDKa7
そもそも大域脱出とやらの定義はどこに示されてるの?

https://www.gnu.org/software/libc/manual/html_node/Non_002dLocal-Exits.html
> 23 Non-Local Exits
> Sometimes when your program detects an unusual situation inside a deeply nested set of function calls,
> you would like to be able to immediately return to an outer level of control.
> This section describes how you can do such non-local exits using the setjmp and longjmp functions.

GNUの文書では単にネストした関数から一気に脱出することだけど?
このスレの文脈としては何か別の特別な定義を参照してるの?
0604はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/12(日) 15:14:46.65ID:b/cm1PRG
言い換えると、
形式としてアンチパターンであるが故にアンチパターンと同等の書き方を強いられていたことに
対する解決 (のひとつ) がラベル付きブレークだろうってこと。
0605デフォルトの名無しさん
垢版 |
2023/02/12(日) 15:17:29.13ID:g76UXZf8
>>602
多重ループからの脱出を形式として優れていると主張するならばわかるが
良き代替策もないのにアンチパターンだと主張するのは意味不明でありそんな主張はほかでも聞いたことがない
0606デフォルトの名無しさん
垢版 |
2023/02/12(日) 15:21:15.66ID:19IYgGC6
アンチパターンなのに解決方法とか自分で言ってて違和感感じないの?
それともアンチパターンだけど必要悪とでも言うのかな?
0607デフォルトの名無しさん
垢版 |
2023/02/12(日) 15:35:28.40ID:bSKw2z5T
アンチパターンとなりうる大域脱出とは、関数呼び出しの奥深く、すなわちスタックレベルの異なる位置からの脱出を指す
一方で、ループやブロックのbreakは同じスタックレベルの出来事であり、当然ながらアンチパターンには該当しない
0608デフォルトの名無しさん
垢版 |
2023/02/12(日) 16:02:50.83ID:CU5K+MKe
アンチパターンの定義も大域脱出の定義もどうでもいいけど
-1を特別なダミー値として-1だったら条件変えてfindとかいうゴミカスクソコードよりは多重ループとbreakの方が遥かにマシなのは間違いない
0609デフォルトの名無しさん
垢版 |
2023/02/12(日) 16:27:13.73ID:haDD5+eS
>>592
>>608
気になるならOption<u8>に変えればいいし、それで大した差なんてないよ
ちょっとRangeで楽できなくなるだけ
それくらいすぐ分かってくれ
0610デフォルトの名無しさん
垢版 |
2023/02/12(日) 16:30:50.77ID:3RfSmBLj
そういうやりとりしなきゃいかん時点でもうラベルブレークのほうがマシやん
0611はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/12(日) 16:39:36.79ID:b/cm1PRG
>>606
「パターンとして分類すると」「形式としては」アンチパターンに当てはまるだろう (実態はそうではない) と言ってる。
要するにアンチパターンではないと言ってるつもりなんだけど。
0612デフォルトの名無しさん
垢版 |
2023/02/12(日) 16:40:20.30ID:U4JchgwQ
>>609
どんどんコードがガチャガチャ読みにくくなっていくので素直に多重ループとbreakしますね
0613デフォルトの名無しさん
垢版 |
2023/02/12(日) 16:58:29.66ID:19IYgGC6
>>611
自分が
>>581 > 大域脱出自体がアンチパターンではあるが
と書いたことも忘れたのか?
そもそも形式的とかオレオレ定義の用語で語られても困るし
0614デフォルトの名無しさん
垢版 |
2023/02/12(日) 17:20:45.22ID:sgmbYDnN
デバッガにかけることを考えたらたかが十数行に収まる二重ループを直積という抽象化で隠蔽するより二重ループのまま見せた方がいいよね
直積として宣言的に書こうが結局プログラムは手続きとして実行されるので、過度な抽象化は手続きに展開する思考コストがかかるだけ
0615デフォルトの名無しさん
垢版 |
2023/02/12(日) 17:28:15.80ID:9lLsDKa7
> 大域脱出自体がアンチパターン

制御フローの代わりに例外使っちゃなんね!
ばっちゃが言ってた!
しかし彼女は大域脱出すべてについてではなく
その用法について言及したにすぎないのであった
0616デフォルトの名無しさん
垢版 |
2023/02/12(日) 18:31:37.86ID:3PkLEVOp
「アンチパターン」に反応して急にレス増えすぎ

>>571がアンチパターンなのは多重ループから大域脱出してるからじゃない
多重ループを使った探索と探索で見つからなかった場合の処理を分離できてないからアンチパターンなんだよ

ブロックのラベル付きbreakを無理矢理使おうとした創作コードだからそうなる
0617デフォルトの名無しさん
垢版 |
2023/02/12(日) 18:44:46.39ID:mi2a8+WT
>>616
forの中から帰るときは見つかった場合の処理で、
見つからずにfor文抜けたらデフォルト値を返すなんて処理プロダクトレベルで1億万回使われてるけど
0618デフォルトの名無しさん
垢版 |
2023/02/12(日) 19:14:49.93ID:mvDk5H0/
>>571 の分岐構造
f(i) がtrueならff(i)
g(i, j)がtrueならgg(i)
それ以外は0

>>588 の分岐構造
jが-1ならf(i)がtrueなら Some(i, -1)
jが-1以外でg(i, j)がtrueなら Some(i, j) ただし j != -1
jが-1以外でg(i, j)がfalseなら None

Some で j が-1 なら ff(i)
Some で j が -1 以外なら gg(i)
None なら 0

(^^;;
0619デフォルトの名無しさん
垢版 |
2023/02/12(日) 19:29:12.94ID:9lLsDKa7
論点578:>>571はアンチパターンなのか?
論点587:571って大域脱出なのか?
論点589:>>588 vs 571 どっちがマシか?
論点607:ループやブロックのbreakは大域脱出ではないし当然アンチパターンでもない
論点614:588 は過度な抽象化は手続きに展開する思考コストがかかるだけ
論点618:588 の分岐構造の煩雑さ(^^;;
0620デフォルトの名無しさん
垢版 |
2023/02/12(日) 20:39:11.84ID:g76UXZf8
>>616
代替策を示さずにアンチパターンだと主張するのをそろそろ辞めにしようぜ
まずは代わりのコードを示すべきだ
0621デフォルトの名無しさん
垢版 |
2023/02/12(日) 22:47:32.75ID:GPArZ08q
let result = collection.find_foo().unwrap_or(bar);

find_fooの中で多重ループ使おうがイテレータ使おうがそれは状況に合わせて使い分ければいい
大事なのは適切な単位で処理に意味ある名前をつけて”意図”を伝えるコードを書くこと

特に多重ループで大域脱出させるような処理に名前も付けずダラダラ書くスタイルはRustのような言語では基本的にやっちゃダメ
0622デフォルトの名無しさん
垢版 |
2023/02/12(日) 22:50:21.83ID:GPArZ08q
オジがわかってなさそうだから補足しておくと
見つかった場合と見つからなかった場合を明確に分けられてないのは>>571>>588も同じだからね
0623デフォルトの名無しさん
垢版 |
2023/02/12(日) 23:10:06.96ID:bSKw2z5T
>>616
機能分離の粒度や方法は決まった正確が一つあるものではなく、状況に応じて基準も変わるし、複数の解があり選べることも多い
したがって、処理を分離したコードの方が明らかに望ましいと誰もが思う場合でないと、アンチパターンと言い切るのは過度だと言える

今回の>>571を、探索(=インデックスを得る)機能部分のみに分離できるのはご指摘の通りだが、コードはこうなる
let (i, j) = 'i_j: {
 for i in 0..100 {
  if f(i) {
   break 'i_j (Some(i), None)
  }
  for j in 0.100 {
   if g(i, j) {
    break 'i_j (Some(i), Some(j))
   }
  }
 }
 (None, None)
};
元のコードと比べると、構造も行数も変わっておらず、さらに加えてこの後にmatch (i, j)の処理コードが必要となる
したがって、今回のケースで機能分離するかどうかは好みの範囲であり、元のコードに問題はないと言える
0624デフォルトの名無しさん
垢版 |
2023/02/13(月) 10:01:54.27ID:tHaQAGDN
>>621
>処理に意味ある名前をつけて”意図”を伝えるコードを書くこと
つまりラベル付きブロックでいいよね
現代的なエディタならブロックは折り畳めばいいし、ラベルで名前もつけられるし
何より型推論と?演算子に任せれば済むような非本質的なエラー型の合成というノイズをメインロジックから分離できて"意図"が伝わりやすくなるので
0625デフォルトの名無しさん
垢版 |
2023/02/13(月) 12:37:14.05ID:+RNuQxOU
>>572の比較表に付け加えるとこんな感じか

関数化:
〇機能名の明示 (関数名)
×利用する変数(値)と結果の型推論
〇変数、ライフタイムのスコープ
×環境(変数)のキャプチャ
〇早期脱出
×?演算子のエスカレーション・合成

ラベル付きブロック式:
〇機能名の明示 (ラベル名)
〇利用する変数(値)と結果の型推論
〇変数、ライフタイムのスコープ
〇環境(変数)のキャプチャ
〇早期脱出
〇?演算子のエスカレーション・合成
0626デフォルトの名無しさん
垢版 |
2023/02/13(月) 13:43:55.80ID:rVD9qCig
関数の特徴としては、
○コード記述箇所と実行箇所の分離
○再入可能性
というのがあるな。

まぁ、ブロックは記述箇所と密接に関係しているから当然の話だけど。
0627デフォルトの名無しさん
垢版 |
2023/02/13(月) 13:50:02.53ID:7ltGU2tW
ブロック式はその場でしか呼ばれないから再入可能性はそもそも必要ないね
そしてブロック式がある関数として再入可能性を保証でいいわけだから
0628デフォルトの名無しさん
垢版 |
2023/02/13(月) 16:19:13.75ID:nVAb+0uo
>>623
そういうループを使う現実的なユースケースは
通常の多次元データではなくフォルダとファイルのようなCompositeデータを扱うときだけなので
インナーループから返す値にはiを必要とせずSome(j)で十分になるように作る
もしそれができない場合でも(Some(i), None)はSome(i)に(Some(i), Some(j)はSome(f(i,j))に変換できるようにする
0629デフォルトの名無しさん
垢版 |
2023/02/13(月) 16:27:32.48ID:7ltGU2tW
>>628
勝手に様々な特殊なケースのみに限定して話をしても全く意味がない
さらに二次元インデックスi,jをjだけに折り畳めるという特殊な仮定を持ち出すのも意味がない
そしてインデックスを返す機能の話をしているのにf(i,j)を持ち出すのも意味不明すぎる
0630デフォルトの名無しさん
垢版 |
2023/02/13(月) 16:46:00.57ID:2YgC8DLe
>>624
let message = 'get_latest_unread_message {

break 'get_latest_unread_message Some(Foo::foo_bar(result)

};
とか書くわけ?
0632デフォルトの名無しさん
垢版 |
2023/02/13(月) 16:53:40.18ID:7ltGU2tW
>>631
いくらでも様々なデータ処理があるだろ
狭い範囲の仕事しかしていないから
>>628のような何重もの特殊な仮定だらけになるのだろう
そして我々がしている議題はRustの言語機能の話がメインでそこでの例として汎用的なサンプルコードが出ている
0633デフォルトの名無しさん
垢版 |
2023/02/13(月) 17:52:42.13ID:KPSnAIKi
そもそもラベルいらんよね?(構文上必要なんだろうけど?)
ブロックに区別が必要ない場合は

>>630を例に取ると
let latest_unread_message = 'b { // 変数名がブロックが返す値を表現
break 'b Some(Foo::foo_bar(result)) // 具体例はbreak以降に表現
};

ブロックが二重三重になってるときだけそれを区別したいだけであって?
0634デフォルトの名無しさん
垢版 |
2023/02/13(月) 17:53:01.42ID:Qnq91utV
型推論のおかげで>>626の機能を諦めれば記述量を大幅に減らせるってことなのかな?

>>630
これに、breakで一番内側の名前付きブロック名を省略する記法があれば、こんな感じに出来て、エディターで表示補完も出来るな

let message = 'get_latest_unread_message {

break '' Some(Foo::foo_bar(result)

};
0635デフォルトの名無しさん
垢版 |
2023/02/13(月) 18:03:44.02ID:JcsLcJKH
>>634
ブロックは関数と異なりリエントラントの必要性も概念もない
ブロックは関数内のその場所で呼ばれるだけだから他から不意打ちで呼ばれる対策も必要ない
ブロックが所属する関数がリエントラントを保証しているから大丈夫

そしてブロックのメリットは環境変数をそのままキャプチャできて型宣言は必要なくブロック式の結果も型推論されること
さらに?オペレータがifやmatchやループの時と同様にブロックを飛び越えてくれるからResultを気にせずに値だけの型に専念できる
0636デフォルトの名無しさん
垢版 |
2023/02/13(月) 18:08:53.41ID:Qnq91utV
>>633
なるほどね
いっそラベルをretとかにしてしまえばクロージャっぽく見えるのか

let latest_unread_message = 'ret {
break 'ret Some(Foo::foo_bar(result))
};
0638デフォルトの名無しさん
垢版 |
2023/02/14(火) 06:32:02.86ID:ltJvnJsS
>>633
ラベルは必要
ラベルが付いてるブロック内でのみラベル指定breakができる

例えばforの中でmatchでアーム右辺が無名ブロックで無名breakしている既存のコードはそのブロックをbreakせずforをbreakする
しかしそれら全体がラベル付ブロックに覆われていてラベル付breakしていればラベル付ブロックをbreakできる

既存コードと互換性があり曖昧さもなく良い構文となっている
既存のloop構文からloopキーワードを抜いただけの構文である点からも自然な受け入れやすい構文拡張となっている
0639デフォルトの名無しさん
垢版 |
2023/02/15(水) 22:09:51.65ID:dlA09Lvs
同時に導入されたlet elseも便利やな
それまではif letするたびにネストがどんどん深くなっていって困るかそれを回避するために
let xxx = if let Some(xxx) = foo() { xxx } else ...と三度も変数名を書かされて悲惨だった
0640デフォルトの名無しさん
垢版 |
2023/02/15(水) 23:56:03.48ID:9hF8ZQFZ
どちらも長年Rustで構文的に残っていた不便な点だったから解決してうれしい
0641デフォルトの名無しさん
垢版 |
2023/02/16(木) 09:41:25.47ID:0fEnHwU4
>>639
早速テストコードに使ったら、ifを除去出来て大変満足
0644デフォルトの名無しさん
垢版 |
2023/02/16(木) 12:55:00.75ID:ioeTYM1H
>>642
例えばこれは深さ3段だからギリだけど
どんどん深くなるのを早期continueしたい時にどうする?って話
環境問題などで別関数化も無しでね
for x in iter {
 if let Some(boo) = get_boo(x) {
  if let Some(foo) = get_foo(x) {
   if let Some(woo) =get_woo(x) {
    let pigs = three(boo, foo, woo);
    ...
   }
  }
 }
}
0645デフォルトの名無しさん
垢版 |
2023/02/16(木) 14:44:50.54ID:IZbDt32x
>>644
関数化無しの前提を置かないといけない状況を改善した方がいいのでは?
その例も普通ならxを受け取ってOptionを返す関数に簡単に抽出できるよね?
0646デフォルトの名無しさん
垢版 |
2023/02/16(木) 14:59:14.48ID:ioeTYM1H
>>645
それは無理
実際のコードだと全部揃ってから処理ではなく途中で処理しつつになる
さらにbreakによるfor抜けも入ったりする
さらに使う環境が多くてその別関数へ参照渡しまくりになる
さらに途中でエラーも返るから別関数はOptionではなくResult返しになる
つまり?はOptionに対して直接使えない
0648デフォルトの名無しさん
垢版 |
2023/02/16(木) 16:37:34.02ID:IOzJHldp
関数を分けると?を逃がすことが出来なくなる点など含めて
ラベル付ブロック式の時と同じ話だな
いずれにせよ関数化は愚策でありlet elseによりcontinueするのが正解
0651デフォルトの名無しさん
垢版 |
2023/02/16(木) 18:48:57.26ID:ipVwq1cH
ちゃんとしたプログラマーは無限ループになりそうなところはブレークMAXカウンターやシグナルブレイク出来るように書いてるから大丈夫ですYO!
0652デフォルトの名無しさん
垢版 |
2023/02/16(木) 21:14:40.29ID:ioeTYM1H
サーバーやデーモンなどは同じことを繰り返せるように敢えて無限ループにプログラミングする
0653デフォルトの名無しさん
垢版 |
2023/02/16(木) 22:57:51.48ID:Pjf9kdf2
>>646
なるほどResult<Option<T>>でOptionだけハンドリングしたいパターンならif let使えばネストしていくわな

普通にmatch使えばいい場面だと思うんだが何かlet else使うメリットがあるの?
0655デフォルトの名無しさん
垢版 |
2023/02/16(木) 23:07:53.84ID:Pjf9kdf2
ああif letの結果を受けるように書くからってことね
それ普通は使わないよね
0656デフォルトの名無しさん
垢版 |
2023/02/16(木) 23:15:48.94ID:Pjf9kdf2
let foo = match get_foo(x)? { Some(x) => x, None => continue} が
let Some(foo) = get_foo(x)? else { continue };になると行数が短くなってうれしいということ?
0657デフォルトの名無しさん
垢版 |
2023/02/16(木) 23:15:53.10ID:IOzJHldp
matchを使おうが元の問題これ何も解決しなくね?
>> let xxx = if let Some(xxx) = foo() { xxx } else ...と三度も変数名を書かされて悲惨だった
0658デフォルトの名無しさん
垢版 |
2023/02/16(木) 23:17:38.28ID:Pjf9kdf2
Someの中の文字は何でもいいんだから短いスコープなら同じ名前を律儀に書く必要ない
0659デフォルトの名無しさん
垢版 |
2023/02/16(木) 23:29:57.12ID:IOzJHldp
変数名短くしても結局3度も書かされるのは異常で改善の余地あり
それが1度で済むようになってようやく正常化した
0660デフォルトの名無しさん
垢版 |
2023/02/17(金) 00:34:38.77ID:g5yjih40
swiftのようにguard let ~ elseとしてくれれば
行頭見るだけでguardだとわかって良かったのにな
少し複雑なパターンマッチだとelseが埋もれてしまう
0662デフォルトの名無しさん
垢版 |
2023/02/17(金) 08:35:50.31ID:oqEBt+Sx
if let って可読性悪くない?
0663デフォルトの名無しさん
垢版 |
2023/02/17(金) 08:45:48.10ID:pJPZoXSu
>>662
両方の観点から分かりやすい
普通のletではなく、ifにより条件付きだと分かる
普通のifではなく、letにより新たな変数定義付きだと分かる
0665デフォルトの名無しさん
垢版 |
2023/02/17(金) 10:59:52.09ID:pJPZoXSu
>>664
その観点からはRustではrefutableなのかirrefutableなのかが一番重要な概念になる
噛み砕いて言うと条件付マッチングとなるのがrefutableで無条件マッチングとなるのがirrefutable
Foo { bar, baz, … }はirrefutableパターンだから普通のlet
Some(foo)はrefutableパターンだからif letかlet else
0667デフォルトの名無しさん
垢版 |
2023/02/17(金) 12:26:34.10ID:pJPZoXSu
>>666
letについては既に説明した通り
それはFooとBarは型が異なりエラー
型の一致は必須
struct内の略は...と3つでなく..と2つ
Bar::default()の()は付けてはいけない
型の明示が必要ないならDefault::defaultでもよい
map_or_else(Default::default, |x| …)は
map(|x| …).unwrap_or_default()と書ける
0669デフォルトの名無しさん
垢版 |
2023/02/17(金) 21:38:02.32ID:qS+nEFWX
>>662
elseがある場合はmatchのほうが可読性いい
elseがない単純な場合はif letでも悪くない
ネストすると最悪
0671デフォルトの名無しさん
垢版 |
2023/02/17(金) 22:52:21.88ID:v1GT8Jf5
letするたびにインデントが深くなる言語もあるぞ
そういう失敗を記憶しているおかげで、比較的成功した例を認識できる
0672デフォルトの名無しさん
垢版 |
2023/02/17(金) 23:13:25.95ID:bvL2FhCi
let elseはシンプルなケースじゃないと通常のletと見分けがつきにくい
でもシンプルなケースならlet chainでまとめた方が圧倒的に可読性高まるのでいらない子になりそう
0673デフォルトの名無しさん
垢版 |
2023/02/18(土) 00:32:34.89ID:y3OKvOKg
最初見たとき便利そうだな思ったけど意外と使わない let else
? とか unwrap_or_elseとかで事足りることが多い
あって困るような機能でもないけど
0674デフォルトの名無しさん
垢版 |
2023/02/18(土) 08:01:02.47ID:9aGkHdVC
論駁可能性の有無で区別つくし、elseによる処理文があるのだから、let elseが見分け付かないなんてことはない
if letと同様にlet elseはエラー値を捕獲する構文ではないため、エラー処理に用いないのは当たり前で、?を持ち出す人はその基本を理解できていない
マッチングしない時にcontinueやbreakする時などは、特にlet elseが最も適している
0675デフォルトの名無しさん
垢版 |
2023/02/18(土) 11:02:32.63ID:eA39OBZC
たしかに
でもコンテニューやブレーク書くことが稀
0676デフォルトの名無しさん
垢版 |
2023/02/18(土) 18:28:41.55ID:rgzpiqjp
やってることは同じ早期離脱なのに
新しいバインディングを伴う場合は
breakやcontinueならlet else
returnなら主に?かlet~match
新しいバインディングを伴わない場合はifかmatch

書くのは多少楽になってもこれだけ種類があると読みにくくなる
0677デフォルトの名無しさん
垢版 |
2023/02/18(土) 18:44:10.63ID:57MjTJJD
if letを廃止してmatchだけに統合すればすっきりする
match boolでifも廃止できる
breakとcontinueもmatch boolで括れば済むから廃止できる
0679デフォルトの名無しさん
垢版 |
2023/02/18(土) 20:16:45.16ID:57MjTJJD
C/C++は多重forの多重breakを持たないが状態変数などで工夫して対応できている
0681デフォルトの名無しさん
垢版 |
2023/02/18(土) 20:45:44.21ID:OvD/kb5O
>>679
>工夫して対応できている
これ言ったら自分の発言のブーメランになってないか?
そりゃ言語仕様に盛り込まずに工夫して対応しろってことなら、
なんだって工夫しろで終了じゃん
0682デフォルトの名無しさん
垢版 |
2023/02/18(土) 20:59:41.48ID:1haq86HP
いや、工夫する方が正解という信念とかは持ってなさそう
正解なんてあるわけないという結論から逆算されたムーブじゃないか
0683デフォルトの名無しさん
垢版 |
2023/02/18(土) 21:04:06.66ID:8K7QiAfd
>>677
>>659にある3回書く問題を無視していいなら今でもmatch縛りで書けばいいよね

その方が読みやすくなる面があるのは確か
0685デフォルトの名無しさん
垢版 |
2023/02/18(土) 21:28:03.45ID:1haq86HP
デストラクタがあればgotoの少なくとも一部は許されないことが確定する
なければ雰囲気で決める
0687デフォルトの名無しさん
垢版 |
2023/02/18(土) 23:56:17.68ID:95PypcL7
そりゃアルゴリズムは出来合いのものしか使いませんっていうならcontinueもbreakも使わんだろうな。
0689デフォルトの名無しさん
垢版 |
2023/02/19(日) 00:36:19.05ID:PxbWEijT
昔みたいに関数を長々と書く時代じゃないから
breakやcontinueは関数抽出で不要になることが多くて出番がすごく少ないんだよ
0690デフォルトの名無しさん
垢版 |
2023/02/19(日) 00:45:12.81ID:iJY+vHtr
100行関数の時代の反動で5行の処理でも関数切り出しする時代からのさらに揺り戻しで
最近はむしろ型推論に任せて明示的に型を書かないために全体が一望できる程度の30行ぐらいの関数は増えているので
breakもcontinueも普通によく見かける
0691デフォルトの名無しさん
垢版 |
2023/02/19(日) 00:45:16.79ID:BpqMGyUW
?はunwrap or return (Err/None)
.unwrapはunwrap or panic
欲しかったのはこれらと同じように使える
unwrap or breakとunwrap or continue

でも出来たのは新しい構文のlet elseでしたとさ
0693デフォルトの名無しさん
垢版 |
2023/02/19(日) 06:25:34.88ID:fFCNNJwx
>>692
それはRFCつまり単なる叩き台
無意味に長いサンプルだからThe Rust Referenceでは短く書き換わっている
typestateは適用できないケース、不向きなケース、向いているがそこまでやらなくてもいいと判断するケースがあり
それ以前にlet elseとは無関係だから持ち出して批判するのは揚げ足取りにしか見えない
0694デフォルトの名無しさん
垢版 |
2023/02/19(日) 07:06:24.11ID:C1cC1Qr1
>>686
稀と言ってるだけ
確かに俺はアルゴリズム博士じゃないね
0695デフォルトの名無しさん
垢版 |
2023/02/19(日) 08:40:02.37ID:Y5aKpigf
特定のサンプルに対してこう書けるから要らないと主張したり、
自分は使わないから要らないと主張したり、
それらの主張は何の意味もないことにそろそろ気付かないと
0696デフォルトの名無しさん
垢版 |
2023/02/19(日) 09:32:40.87ID:Qqyqhdv7
関数の「切り出し」とか行数で語ってるのとかまだまだ幼いなってオモタw
最近の流れじゃあ>>689サンだけ一個上のレベルにおるな
0697デフォルトの名無しさん
垢版 |
2023/02/19(日) 10:03:16.21ID:xSIr/CQB
>>685
> デストラクタがあればgotoの少なくとも一部は許されないことが確定する
ならtry〜throw〜catchで
0698デフォルトの名無しさん
垢版 |
2023/02/19(日) 10:56:50.58ID:iJY+vHtr
>>696
君はまだ参照の持ち回りや明示的に型を書くことのデメリットを理解せずになんでもかんでも関数にするレベルにいるんだね
0700デフォルトの名無しさん
垢版 |
2023/02/19(日) 11:13:57.20ID:XqM1QV+K
>>693
最終的なRFCはたたき台じゃないよ
RFCは議論の進行とともに更新された上で提案された機能を採用するどうかを判断するための公式ドキュメントとなる
採用決定後に書かれるリファレンスとは全く役割が違う
0701デフォルトの名無しさん
垢版 |
2023/02/19(日) 11:21:38.84ID:Y5aKpigf
>>689
関数切り出しでは出来ないこともあれば無駄な記述が増えることを含
めて様々なデメリットもあるから、
それらをクリアできて上回るメリットがある時に絞って使い分けるとよい
あと関数切り出しすれば何でもcontinueやbreakという制御構造を無くせるわけでもない
そして君の使い方だと出番がないからそれらが不要だとの主張には何の意味もない
0703デフォルトの名無しさん
垢版 |
2023/02/19(日) 13:11:23.57ID:zmZHaY7K
>>688
フフッ、奴らはRust魔術師なんて名乗ってるが所詮は、正確な儀式魔法陣の設計と、正確で美しい呪文の詠唱にこだわる愚物よ!
それで発動するのが初級のファイヤーボールたるファイル検索とか笑えるだろ?
無詠唱でループで取り囲まれている敵陣真っただ中に転移ジャンプすることすら叶わぬのだッ!
0704デフォルトの名無しさん
垢版 |
2023/02/19(日) 14:21:00.44ID:LfhOnc3U
>>702
ユーザーマニュアルと開発時の要件定義書や設計書の違いだよ
承認された最終版の要件定義書や設計書をたたき台と呼んでる会社なのかな?

提案資料と捉えても別に構わないとは思うが
採用判断の妥当性を確かめるために参照するのは間違ってもユーザーマニュアルではない
0705デフォルトの名無しさん
垢版 |
2023/02/19(日) 14:23:05.09ID:k7Ha0AgI
実装は正確に、商談はいい加減にやればいいのに
消費税込み0円で物々交換することすら叶わぬのだ
0706デフォルトの名無しさん
垢版 |
2023/02/19(日) 14:26:53.65ID:Qo8ZRnUl
>>673
Option,Resultならunwrapで良いけど、任意のenumから同じように中身を取り出す方法ある?
0707デフォルトの名無しさん
垢版 |
2023/02/19(日) 14:33:14.38ID:GfHJyYZp
if letとlet elseがmatchのsyntax sugarなのは自明だから
RFCのサンプルという特定の例に対して別の書き換えが可能だと主張しても何の意味もない
if/let/elseという既存の概念と既存のキーワードの組み合わせによりmatchより短く書けて利便性も良いと総合的に判断されてRustに導入された
0708デフォルトの名無しさん
垢版 |
2023/02/19(日) 14:44:02.93ID:xSIr/CQB
>>704
> 承認された最終版の要件定義書や設計書をたたき台と呼んでる会社なのかな?
お前さんが
>> だから議論中は
という簡単な文章すら理解できないことはよくわかった
0709デフォルトの名無しさん
垢版 |
2023/02/19(日) 15:44:36.19ID:iJY+vHtr
RFCは叩き台だと思う

たたき‐だい【×叩き台】
読み方:たたきだい

批判・検討などを加えて、よりよい案を得るための原案。
0712デフォルトの名無しさん
垢版 |
2023/02/19(日) 16:00:56.96ID:K3OK+ZQ9
RFCに議論の過程もなぜ導入しようとしたのかもメリットも書いてるのに
サンプルコードが別の書き方できるってもう重箱隅つつきたいだけでしょ
せめてRFCテキスト一文に対する反論なり書いてれば議論になるんだろうけど
0714デフォルトの名無しさん
垢版 |
2023/02/19(日) 16:09:05.87ID:Y5aKpigf
let elseの話ならばもはやRFCの段階ではなく、
既に正式にlet文の一部として位置付けられて取り込まれており、
公式Referenceにもletの機能として必要な条件などが記載されている段階
0715デフォルトの名無しさん
垢版 |
2023/02/19(日) 16:26:24.12ID:Y5aKpigf
RFC (request for comment)はもちろんその名の通り『叩き台』で合ってる
ただしlet elseについては既に結論が出ているので、
RFCのtracking issueと合わせて過去の経緯と議論を見るための存在へと変わっている
今はRust公式Referenceを見るだけで十分
0717デフォルトの名無しさん
垢版 |
2023/02/19(日) 17:04:26.59ID:GfHJyYZp
3ヶ月も前にstableに導入されたlet elseやラベル付ブロックbreakを今になって自分は使わないからその機能は不要だと主張している人は何をしたいのだろう?
時期的にも不明であるし執拗に不要だと言い続けている意図も不明だ
同時に導入されたGATも使わないから不要と言い出しそうだな
0719デフォルトの名無しさん
垢版 |
2023/02/19(日) 17:58:31.87ID:bwwdc6fu
そもそも要らん機能だと言い張るならRustフォークして削除した版作って勝手にやってりゃいいと思う
0722デフォルトの名無しさん
垢版 |
2023/02/19(日) 20:04:13.68ID:C1cC1Qr1
有意義ではないとは言ってない
使うのは稀だと言ってるだけ
稀で済むからRustを使ってるの
0723デフォルトの名無しさん
垢版 |
2023/02/19(日) 20:21:42.49ID:iJY+vHtr
Cの時代にはgotoは普通に要る機能だったからな
コンパイラも今ほど賢くないし
0725デフォルトの名無しさん
垢版 |
2023/02/19(日) 21:45:08.41ID:iJY+vHtr
gotoがメモリ消費量や実行性能の関係で最適になるケースがあった
コンパイラの最適化も今ほど優秀でなかった
0726デフォルトの名無しさん
垢版 |
2023/02/19(日) 22:08:56.75ID:GfHJyYZp
C/C++でもラベル付break/continueをサポートすればgotoを廃止できるけど
過去のgoto文があるために手を付けれないだけでなくwarning化することもなく
ラベル指定break/continueも導入せずにgotoのままでいいやと怠慢かなあ
どうしてもgoto避けたいなら無駄にフラグ変数利用
0727デフォルトの名無しさん
垢版 |
2023/02/19(日) 23:43:41.66ID:3jtI5gR6
let elseはErrにアクセスできたなら
Option/Result系の早期離脱はlet elseに統一できてよかったんだけどね

それができないから?オペレータが使えないbreak/continueか
Errにアクセスする必要のないOption::ok_or_else + ?の代替
0729デフォルトの名無しさん
垢版 |
2023/02/20(月) 00:29:43.00ID:Ro8B3+Pr
>>727
if letとlet elseは対であり対称な存在だから
「Errにアクセスできたら」なんて意味不明なことを言い出してる時点でif letも理解できていない
まずはif letが適していることとできないことを勉強し直しなさい
0732デフォルトの名無しさん
垢版 |
2023/02/20(月) 00:47:31.51ID:Ro8B3+Pr
>>728
中身を取り出す方法を具体的に尋ねられているのに「抽象化すれば」では答えになっていない
0733デフォルトの名無しさん
垢版 |
2023/02/20(月) 01:16:24.28ID:Ro8B3+Pr
>>731
既存コードをlet elseへと適しているのを置き換えたから把握している

Err(e)値も処理したいときに
if let Ok(v) = ...と書かないのと同様に
let Ok(v) = ... elseも同じく使わないのは当たり前
それはどちらもmatchやResultメソッドを使うべきケース

もしf()がResult<enum, Error>を返す場合ならば
if let Xxx(v) = f()? ...とErrだけ逃がすことができるし
let Xxx(v) = f()? ... elseとErrだけ逃がすことができる点も同じ
0735デフォルトの名無しさん
垢版 |
2023/02/20(月) 08:12:59.13ID:+rcREq9r
RFCの段階での議論に敗北して採用されちゃったからって5chでギャオってるの見苦しすぎるだろ
0736デフォルトの名無しさん
垢版 |
2023/02/20(月) 08:32:05.17ID:odEeQ6ui
機能追加は自分の思いつくことを解決する、または大幅な改善をする
銀の弾丸でなければならないって思ってそうだ
0737デフォルトの名無しさん
垢版 |
2023/02/20(月) 10:59:06.46ID:Dw9X3Ven
条件つき確率を信じない人のような印象
条件が成立しなければ普通の弾丸だから
0739デフォルトの名無しさん
垢版 |
2023/02/20(月) 13:36:11.72ID:LGz5jnMj
「と言い出しそうだな」「って思ってそうだ」「な印象」

関心事がけっきょくは発言者の人格なんでつねえw
0741デフォルトの名無しさん
垢版 |
2023/02/20(月) 18:04:32.79ID:Ro8B3+Pr
ただ文句をつけたいだけなのか
とにかく嫌いなだけなのか
ブロックラベル指定breakについてもlet elseについても反対してる人から一貫性や理性を感じられない面はある

例えばlet elseについて不要との主張の理由がこれまで3つ挙げられているが
「自分は使わないから不要」は論外として
「他の書き方ができるから不要」も特定の例にしか適用できない代替策だったり当然if letとlet elseはmatchに代替できる原点の視点を欠いている
「Err(e)値を扱えないから不便で不要」も同様でif letとlet elseはそれを扱わない構文だと理解できていない
もしif letも不要だと開き直るならばそれはそれで主張が一貫しているのであろうが
0742デフォルトの名無しさん
垢版 |
2023/02/20(月) 18:35:32.36ID:ONCzk40Q
ぱっと見の印象ほど便利でもないな
と言われてるだけのような気がするが
0744デフォルトの名無しさん
垢版 |
2023/02/20(月) 18:59:27.30ID:epDqj6rM
冷静な技術的議論にならない原因が誰にあるかは一目瞭然なんだから相手にしないこと

分かりやすい煽りよりも技術的議論に見せかけたマウンティング行為にこそ高いスルー力が求められる
0745デフォルトの名無しさん
垢版 |
2023/02/20(月) 19:34:52.06ID:z/noiTmG
煽りこそ要らない
技術的な議論なら歓迎
マウンティングとか興味ないためそんな発想も感覚も出て来ないので感じている人はたぶんそれ鏡の自分自身
0746デフォルトの名無しさん
垢版 |
2023/02/20(月) 19:56:45.86ID:KVc2H5on
技術的論議とか不要やん
売れるシステム作ったもんの勝ちや

でもって世の中で売れてるシステムって意外とクソ技術
0748デフォルトの名無しさん
垢版 |
2023/02/20(月) 20:50:17.61ID:z/noiTmG
>>746
ここはプログラミング言語Rustのスレ
興味がないならば別スレへどうぞ

>>747
昼間に書き込んでるIDを見たらあんたやでw
0749デフォルトの名無しさん
垢版 |
2023/02/20(月) 20:55:08.90ID:KVc2H5on
>>748
勘違いしちゃいけない
言語には興味があるが今行われてる議論には興味も無いし意味もない
0750デフォルトの名無しさん
垢版 |
2023/02/20(月) 21:14:07.07ID:3GUDPmP7
何年も前からRFC出てて昨年stabled入りした機能に要るも要らねえもねえからな
0751デフォルトの名無しさん
垢版 |
2023/02/20(月) 21:18:07.99ID:z/noiTmG
stableになった11月に不要だと暴れるならともかく
今になって不要だと暴れてるのも不思議だよな
0752デフォルトの名無しさん
垢版 |
2023/02/20(月) 21:21:42.34ID:Dr+y9QH4
🦀

みんながインターネットで争ってばかりいるので、Ferrisくんは踊るのをやめてしまいました
お前のせいです
あ~あ
0753デフォルトの名無しさん
垢版 |
2023/02/20(月) 21:31:44.32ID:Gnfu+Wjk
RFCに特攻しないだけマシなのでは
いや公式に真正面からお伺いたてたほうがマシなのか
0754デフォルトの名無しさん
垢版 |
2023/02/20(月) 21:53:45.15ID:LGz5jnMj
暴れてる、ってのが被害妄想的表現やわ
俺には誰一人暴れてるようには見えない
このスレで暴れてたのは所有権の複製のあの人だけ
0755デフォルトの名無しさん
垢版 |
2023/02/20(月) 22:53:31.02ID:5X4Ju8b5
繰り返し同じ主張をしても誰も同意してくれないから
自分の意見に同意してくれないやつらは全員暴れてるということにして無意識に自我を守ろうとしてるんだよ

自己愛的防衛とか躁的防衛というやつ
0756デフォルトの名無しさん
垢版 |
2023/02/20(月) 23:30:32.01ID:5j6SE1ew
>>754
所有権の複製ってもう5年くらい前だろ
そんな昔のことをいまだに引きずってるとは病んでね?
何の記事に書いてあった話かも忘れた
0758デフォルトの名無しさん
垢版 |
2023/02/21(火) 01:55:16.33ID:Z2SDCDpJ
頭が良くなれば解決することを、性格や健康の問題だと思わないほうがいい気がする
頭が良くなりたいのは色々解決するからだ
マウントしたいからではない
0759デフォルトの名無しさん
垢版 |
2023/02/21(火) 02:05:43.32ID:KRj8g2tD
俺たちが興味あるのは技術の話題であって他人じゃねーもんな
誰がどうしたとか妄想に取り憑かれているとしか思えん
ところで標準ライブラリがflumeではなくcrossbeamを取り込んだのはなんでだ?
0762デフォルトの名無しさん
垢版 |
2023/02/21(火) 21:08:16.69ID:QxhrM2ln
std::sync::mpscの実装が5年くらい放置されてた
その間に効率的な実装のcrossbeamが広まり更に効率の良いflumeも登場して性能と人気を競っている
放置されてた標準ライブラリを今回は実績のあるcrossbeam実装ベースへ変更したが状況は変わらないだろう
Rustは最小限の標準ライブラリに様々なクレートが競い合ってより良いものを生み出していく文化であるからだ
0764デフォルトの名無しさん
垢版 |
2023/02/21(火) 22:02:42.80ID:MpX1NcOI
自分の発言が炎上するかしないかを自分で判定できそう
失言おじさんにはそれができない
0768デフォルトの名無しさん
垢版 |
2023/02/21(火) 22:28:06.23ID:y29mFsWC
「所有権の複製」とかいうアホな用語を使って
ここのみんなにバカにされて涙目で敗走していったおじさんがおるんよ
その可愛そうな子が複オジ
0770デフォルトの名無しさん
垢版 |
2023/02/21(火) 23:07:04.37ID:3NMnjtHz
>>768
誰かが「所有権の複製」と言い出したのではなくITメディアサイトのRust入門記事に書かれていた話だな
その表現を許容できる範囲か違和感あるかで色んな意見があったのは覚えている
0772デフォルトの名無しさん
垢版 |
2023/02/21(火) 23:29:58.13ID:01DiY+Ot
Copy実装型は値が複製されて新たな所有権が生じるが正確
それをその入門記事は所有権の複製と表現してたやつだろ
許容でも不許容でもどうでもええわ
0777デフォルトの名無しさん
垢版 |
2023/02/21(火) 23:44:49.64ID:4zIxg9qg
そんな昔の話をいまだに引っ張ってオジオジ言ってたのかよ
精神病んでるな
0778デフォルトの名無しさん
垢版 |
2023/02/21(火) 23:54:33.49ID:MG8QCGMu
C言語は知ってる。アセンブラも知ってる。どうやってメモリ安全なのか
サクッと説明できないの?
0779デフォルトの名無しさん
垢版 |
2023/02/21(火) 23:57:49.69ID:+CfSou71
文句あるならRFCとか記事サイトとかに直接言うしかないな
ここでこれ以上の議論を続けてもしょうがない
0781デフォルトの名無しさん
垢版 |
2023/02/22(水) 00:14:21.77ID:Y34Ut0PO
複製の方はググってみたらitmediaのRust入門記事だね
型に依って移動と複製の2種類あるのを教えるところだから、入門者向けの解像度として大雑把にしといて後で詳細を学べばいいでしょ

メモリ安全の方は解説記事が山ほどあるから、まずは読んで分からないところだけを質問したら?
0782デフォルトの名無しさん
垢版 |
2023/02/22(水) 00:45:10.48ID:kRg6p3dR
参照されている間はmove禁止にする
それができたらその意味で安全
どうやってそれができるのか実装依存かな
0783デフォルトの名無しさん
垢版 |
2023/02/22(水) 00:59:45.76ID:Y34Ut0PO
稀に誤解する人がいるけど、moveはメモリ上の移動ではなく所有権の話だから注意ね
メモリ上の移動の禁止を保証するのはstd::pin::Pinだけど、初心者は知らなくても大丈夫
0784デフォルトの名無しさん
垢版 |
2023/02/22(水) 01:45:26.03ID:7qIc4ux9
moveを所有権の移動だと捉えてるから
copyも所有権の複製だと勘違いする
これが世に言う複製おじさん
0786デフォルトの名無しさん
垢版 |
2023/02/22(水) 11:19:00.04ID:QrBlGoqy
>>783
一応ちゃんとCopyのdocで「It’s important to note that in these two examples, the only difference is whether you are allowed to access x after the assignment. Under the hood, both a copy and a move can result in bits being copied in memory, although this is sometimes optimized away.」って説明されてんだよな
0789デフォルトの名無しさん
垢版 |
2023/02/22(水) 16:14:06.54ID:TLbBZAeA
メモリ安全に関しては実行時の、
すなわち実装上の工夫があるわけでは一切なく、
単にメモリの使途をコンパイラが把握できるようにして
コンパイラが厳しいチェックを入れるってだけのことなのかな
極めて有用だと思うけどつまんないね
0791デフォルトの名無しさん
垢版 |
2023/02/22(水) 16:30:09.13ID:rz+Hc8C4
>>789
実装上の工夫をコンパイラが自動的に出来るように、メモリの使途をコンパイラが把握できるようにしているんじゃないの?
0792デフォルトの名無しさん
垢版 |
2023/02/22(水) 16:59:49.22ID:TLbBZAeA
>>791
出来上がるプログラムのメモリ実装はC/C++並みに速く、
なのにそれはコンパイラの厳しいチェックをくぐってて安全
それだけのことでしょ
0793デフォルトの名無しさん
垢版 |
2023/02/22(水) 18:54:03.56ID:pxjFrvRx
他言語由来なんだろうけど、moveという命名はセンス無いわな。
transferあたりならまだマシな気がする。
0794デフォルトの名無しさん
垢版 |
2023/02/22(水) 19:30:38.74ID:LddiDqOW
moveがふさわしい
ドキュメントでも至るところでmove or copyと対比され使われている
transfer or copyではおかしい
0795デフォルトの名無しさん
垢版 |
2023/02/22(水) 22:03:03.74ID:9y2tPN5s
moveやcopyの対象はvalue
ownershipはtransfer(譲渡/移転)されたりtake(取得)するもの

moveとcopyが対比されるのは同じ対象について述べているものだから当たり前
0797デフォルトの名無しさん
垢版 |
2023/02/22(水) 22:32:54.84ID:ejRdyGcN
同じことを言い合っていて、間違ったことを言ってる人もいなさそうだが、何をもめているのだろう
0799デフォルトの名無しさん
垢版 |
2023/02/22(水) 22:46:55.03ID:SB7jqjIk
>>793だけ理解できていない
Rustで使われているmoveという用語は所有権が移動することで値が移動する概念を指す
例えばエラーメッセージのmove occursなどのmoveはその事象を指している
だからそこはtransferではなくmoveで正しい
0800デフォルトの名無しさん
垢版 |
2023/02/22(水) 22:59:45.22ID:H3r2EuTC
RustはC++から輸入して所有権って言葉を使っているだけであって
C++で言う「所有権を失ったがオブジェクトとしては存在している」みたいな状態は少なくともsafe Rustには無いからね
だから値と所有権を切り離して考えるだけ無駄
0801デフォルトの名無しさん
垢版 |
2023/02/22(水) 23:28:17.85ID:ejRdyGcN
値と所有権を切り離して考えてもムダなのはその通りだね
値には必ず所有者(owner)すなわち変数が対応してる
そして所有者である変数がスコープを尽きて消えるときに値もdropで消える
だから切り離すことはできない

値が消えないためには所有者である変数のスコープが尽きる前に、他の変数へ代入か、関数引数渡しか、関数戻値返し、をしなければならない
その時にCopy実装型だと値が複製されて渡した先にも別の所有者が生じて各々が別の人生を辿る
!Copy実装型だと値が「概念的に」移動して渡した先に所有者が変わる
この両者の違いを端的に表した用語がcopyとmove
0802デフォルトの名無しさん
垢版 |
2023/02/22(水) 23:31:46.84ID:9y2tPN5s
所有権が「移る」という意味の英訳として「move」という単語を当てるのが間違ってるわけではないが
「所有権を複製する」といった致命的な間違いを生む原因になってるの可能なら避けた方が良い
0803デフォルトの名無しさん
垢版 |
2023/02/22(水) 23:55:25.59ID:ejRdyGcN
>>802
いや、所有権に対して直接moveと言っているわけではないんだよ
値の所有者(=変数)が変わることを、視点を変えると、旧所有者から新所有者へ値が移動している、それはさらに視点を変えると、所有権が移動していると表現してもいいわけだけど、
それら視点は様々あるけど同じことを指してRustでは『move』と呼んでいる
だから所有権(ownership)という単語に対して一般的な英語の用法として動詞にtransferやtakeを文章では使うけれど、そのこととは全く関係ない
0804デフォルトの名無しさん
垢版 |
2023/02/22(水) 23:57:57.68ID:H3r2EuTC
いや、そんな状態が無いはさすがに嘘か……
Option<T> where T: Dropのtake()は実質ムーコンみたいなことやるし

所有権=リソースの解放義務と考えればそもそも!Dropには所有権なんてものは存在しないって考え方が正しいのかねえ
0805デフォルトの名無しさん
垢版 |
2023/02/23(木) 00:13:31.19ID:C4cWdlsx
>>804
その場合も値と所有者は単体には生じてない
take()で新しい所有者に値が移動している
ただしデフォルト値のNoneにスワップされるため元の所有者も生きたままというだけ
これは一般的にはstd::mem::swap(),replace(),take()であり
互いに相手にmoveが生じただけ
0807デフォルトの名無しさん
垢版 |
2023/02/23(木) 00:58:28.47ID:esRNNZX1
やっと分かったかも
コードのある時点において、仮にその時点での継続を全部消したとき、Drop::dropが自動で差し挟まれることになるブロックはその時点でそのリソースを所有している、と解釈できるわけか

というのがNLL以前の話ってやつなんだなたぶん
そうなると所有の主体はブロックじゃなくてライフタイムってことになるのかね?
0808デフォルトの名無しさん
垢版 |
2023/02/23(木) 01:29:31.74ID:rq0OeSBM
どうしてドキュメントと違う言い回しの独自解釈を捻り出そうとしてしまうのか。
0810デフォルトの名無しさん
垢版 |
2023/02/23(木) 02:02:47.49ID:bPCulnq5
>>807
値の所有はそれを他へ渡さない限りレキシカルにブロックスコープが尽きるまで続く
ただし参照のライフタイムについてはレキシカルなスコープではなく実際の使われ方に応じて短くなりうる
例えば非可変参照を使っていて、後から可変参照を使うことになった時は、
それらが重なってなければ非可変参照のライフタイムは終わった扱いにして、同じブロックスコープの中で新たに可変参照を借用できるのがNLL
0812デフォルトの名無しさん
垢版 |
2023/02/23(木) 09:29:02.67ID:BoWU7ZWJ
以前指摘されたDrop Obligationを今になって勉強して一人芝居してるw
ほんと滑稽な人やでww
0813デフォルトの名無しさん
垢版 |
2023/02/23(木) 09:41:47.82ID:nQ2ppFvg
説明をわかりやすくするために創作された抽象概念と実装が1対1で結びついてるわけないのにね
0814デフォルトの名無しさん
垢版 |
2023/02/23(木) 09:55:07.36ID:FonN/9hK
>>800
>「所有権を失ったがオブジェクトとしては存在している」
値が所有権を持ってるわけじゃないから
0816デフォルトの名無しさん
垢版 |
2023/02/23(木) 11:25:42.30ID:pfd9YhIH
値に所有権フラグ的なものがくっついてるイメージでとらえてしまってるんでしょ
だからコピーしたら所有権も複製されるし
値と所有権を切り離して考えても無駄だと勘違いしてしまう
全部つながってる
0817デフォルトの名無しさん
垢版 |
2023/02/23(木) 11:47:29.47ID:suv8L/am
>>816
値と所有者はそれぞれ単独に存在できないので、値と所有者を切り離して考えても無駄なのはRustの基本たぞ
値は必ず所有者を持つし、所有者は必ず値を持つ
0819デフォルトの名無しさん
垢版 |
2023/02/23(木) 13:34:12.46ID:esRNNZX1
>>807
っていうかそこまで難しい話じゃなくて
move a value と transfer its ownership を同義語として、自然言語としてわかりやすいように適宜言い分けてるだけなのか?

じゃあ結局「ownershipとは〜〜」という形でのownershipの定義なんてものはRustにはない?
公式のドキュメント検索しても見つからなかったんだよね
0820デフォルトの名無しさん
垢版 |
2023/02/23(木) 13:44:46.02ID:lWMy0tB5
>>817で合ってるよ
オジ使いの人は文句をつけることが主目的なのか正しいことにも文句をつける印象
0821デフォルトの名無しさん
垢版 |
2023/02/23(木) 13:46:51.41ID:a6t3KRYM
不動産みたいな移動できないものの代わりにその所有権を移動する
メモリ上では実は複製と消去しかできないので本当は移動ができない
0822デフォルトの名無しさん
垢版 |
2023/02/23(木) 13:56:15.25ID:lWMy0tB5
>>821
そこの理解が重要だよね
あくまでもmoveは概念上のもの
だから皆が概念という単語を使っているね

>>799
> Rustで使われているmoveという用語は所有権が移動することで値が移動する概念を指す

>>801
> !Copy実装型だと値が「概念的に」移動して渡した先に所有者が変わる
> この両者の違いを端的に表した用語がcopyとmove
0823デフォルトの名無しさん
垢版 |
2023/02/23(木) 14:13:14.00ID:lWMy0tB5
そしてmoveの概念とは異なりmoveの実際の生成コードは最適化によって多種多様
基本はmove先に複製して元が無効となるけど、最適化によって複製が発生せずそのまま使ったり、
関数でサイズがある程度あるものをmoveで返す場合には、関数呼び出し元のスタック上に呼び出し先関数から直接書き込んでしまったりもする
0827デフォルトの名無しさん
垢版 |
2023/02/23(木) 18:26:04.33ID:G9ttzE8v
moveは値と所有権の移動
copyは値と所有権の複製
cloneは値と所有権の複製
borrowは値と所有権の借用
mut borrowは値と所有権の書き換え可能な借用

(๑•̀д•́๑)何ら問題ないキリッ
www
0828デフォルトの名無しさん
垢版 |
2023/02/23(木) 19:16:28.85ID:3Mx58NHj
所有権の複製って聞いておかしいと思わない子もそりゃいるよ
みんなが賢いわけじゃなくて残念ながらアホな子もそりゃいるんだよ
あんまりいじめてやるなよ
0829デフォルトの名無しさん
垢版 |
2023/02/23(木) 21:37:16.18ID:a6t3KRYM
弱者は強者に負けるとかいう理論もまた創作なのに
創作と現実が一致するまで戦争をやめられない現象は実際に起きている
0830デフォルトの名無しさん
垢版 |
2023/02/23(木) 22:01:41.01ID:6fqNKB/7
よほど誤解を招きやすい情報ソースがあるのか
それともここにはアホの子しかいないのか
はたまた一人が暴れているだけなのか
0831デフォルトの名無しさん
垢版 |
2023/02/23(木) 22:02:05.98ID:vkbZDErw
C++のリファレンスカウンタの仕組みからやってないヤツにはちんぷんかんぷんだろうぜ
0832デフォルトの名無しさん
垢版 |
2023/02/23(木) 22:14:56.65ID:A0wb20Dk
経緯は>>770の通りだろうけどそんなに引っ張る話なのかがわからんね。
それで実害があるならともかく。
0834デフォルトの名無しさん
垢版 |
2023/02/23(木) 22:41:43.47ID:6seZ46P8
>>830
>はたまた一人が暴れているだけなのか
100%これ
数ヶ月このスレにいれば自ずとわかってくる
0836デフォルトの名無しさん
垢版 |
2023/02/23(木) 23:14:02.76ID:7+yv+Q2n
>>823
Rustは様々な点で実装(生成コード)と概念を明確に分けてるね
概念の部分だけを保証するから最適化の余地が大きくて良い感じ
0837デフォルトの名無しさん
垢版 |
2023/02/23(木) 23:43:30.64ID:a6t3KRYM
概念にも最適化があって概念の「わかりやすさ」を最適化するために
moveとtransferどっちが優れた概念かを決めるバトルをやってたんだな
0840デフォルトの名無しさん
垢版 |
2023/02/24(金) 06:23:24.59ID:CUSdLGN9
Interface 2023年5月号予告
Cと比較して理解する 質実剛健 Rust言語
3月25日発売 (定価 1,200円+税)
0841デフォルトの名無しさん
垢版 |
2023/02/24(金) 16:52:10.17ID:nsUeAOhk
動かして学ぶ!Rust入門
発売日:2023年04月24日
定価:3,960円

【本書の概要】
Rustのプログラミング手法について、サンプルを元に手を動かしながら学ぶ書籍です。主に以下の3つについて丁寧に解説します。

●Rustの概要と開発環境
●Rustの基本的な文法と機能
●Rustによる簡単なアプリ開発

なお本書はエンジニアのための情報共有コミュニティ「Zenn」で公開されている大人気の「Rust 入門」を元にした書籍です。

【対象読者】
Rustに初めて触れるプログラマー

【本書のポイント】
・基本的な文法について丁寧に解説
・Rustの機能を学ぶのに適したサンプルを用意
・学習をもっと深めたい方に向けて「メモ」や「参照」で補足

【目次】
Chapter1 Rust
Chapter2 環境構築
Chapter3 Rustの文法と機能
Chapter4 アプリケーションの開発
0842デフォルトの名無しさん
垢版 |
2023/02/24(金) 16:55:36.65ID:7VL6jHM8
>なお本書はエンジニアのための情報共有コミュニティ「Zenn」で公開されている大人気の「Rust 入門」を元にした書籍です。

あーはいはい
結構です
0843デフォルトの名無しさん
垢版 |
2023/02/24(金) 17:23:39.58ID:C63NsF8r
https://zenn.dev/mebiusbox/books/22d4c1ed9b0003/viewer/30450c
束縛
> let 文を使うことでオブジェクトと変数を 束縛 します.変数はそのスコープから外れたときに束縛していた所有権を放棄します.
> また,最初に束縛したオブジェクトの所有権は基本的に原本となり,原本および仮の所有権がすべて放棄された時にオブジェクトは破棄されます.

原本?
仮の所有権?

( ^ω^)…
0845デフォルトの名無しさん
垢版 |
2023/02/24(金) 18:03:47.03ID:m9pgynCe
少し読んでみたけど笑いを通り越して背筋が凍るんだが

ほんとにこれの書籍化?
URL間違ってない?
0847デフォルトの名無しさん
垢版 |
2023/02/24(金) 18:18:05.46ID:C63NsF8r
オレオレ用語満載の書籍が
初心者界隈に何をもたらしてしまうか…
発売前にぜひご一考願いたい( ^ω^)
0848はちみつ餃子 ◆8X2XSCHEME
垢版 |
2023/02/24(金) 19:58:43.81ID:4A+eO5tS
仮に (あくまでも仮に!) 完全に挙動を説明できているのだとしても
他の人が書いた説明と合わせて読もうとしたら食い違うわけだろ。
書いている人はわかりやすく言い換えてるつもりなんだろうとは思うけど
学習過程全体を考えたらあんまりわかりやすくなってない。

Rust の全てをカバーしてて他の資料を読む必要がないくらいに充実してるなら
独特の定義で押し通すのもありかもしれんが、現実にはそんなことありえないしな……。
0849デフォルトの名無しさん
垢版 |
2023/02/24(金) 19:59:12.46ID:e5dQOFE4
>>843
オブジェクトという単語は各プログラミング言語で様々な意味で用いられているが
Rustでその文脈で用いられることは少なく
その説明ではオブジェクトではなく値(value)とした方がよい

Rustで用いられるオブジェクトの用法の多くはtrait objectであり
Rustで重要なオブジェクト安全もtrait objectの話
0850デフォルトの名無しさん
垢版 |
2023/02/24(金) 20:03:54.76ID:C63NsF8r
>>848
> 他の人が書いた説明と合わせて読もうとしたら食い違うわけだろ。
> 書いている人はわかりやすく言い換えてるつもりなんだろうとは思うけど
> 学習過程全体を考えたらあんまりわかりやすくなってない。

そうそれ
無駄で邪魔でしかない
独自用語を野放図に用いる傲慢さ
用語の正しさに対する誠実さが無い
0851デフォルトの名無しさん
垢版 |
2023/02/24(金) 20:09:21.33ID:hzPT7xYj
パーフェクトRust買った
これまで日本人の書いたRust本の中で1番良い出来だな
変なところに偏ってないし
0852デフォルトの名無しさん
垢版 |
2023/02/24(金) 20:18:59.08ID:kQOezMEX
参照が入ってる変数は仮でもなんでもなく参照の所有権を持ってるのに仮の所有権とか言われても困る
0853デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:02:52.36ID:a3OsZb0h
オブジェクトと所有権を切り離せないものと考えてる辺り>>800と全く同じ見解じゃん
ご本人様ではないですよね?
0854デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:17:18.19ID:X6Gu9Bob
たぶん参照自体じゃなく参照されてる値に対する「借用」のことを「仮の所有権」と表現してる

当然のように「オブジェクト」って言葉を使ってるけどもう少しvalueに寄せてほしいな

>> オブジェクト
>> 数値や関数や参照など,型の実体はすべて**オブジェクト**です.
>> つまり,式が返す値もまたオブジェクトになります.
>> 例えば, 1 という値も数値オブジェクトであり,1 == {1} という関係にあります.

ここの進次郎構文は何を表現してるの?
{1}が1なのはブロック式だからなんだけど
0856デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:23:19.34ID:e5dQOFE4
>>852
参照の所有権とは言わない
値に対する所有の唯一性が所有権で
値に対する参照が借用
そして所有>借用の生存期間ルールを満たした上で所有のスコープルールとなるため、

>>843
>> 原本および仮の所有権がすべて放棄された時にオブジェクトは破棄されます.

この文章の各用語を「仮の所有権」→「借用(参照)」など全て正しく書き換えても根本が間違っている
この説明だと参照が残っていれば所有者がいなくなっても破棄されないことになってしまうため
0858デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:39:26.62ID:C63NsF8r
一個一個挙げてってもキリがないけど

> 所有権
> オブジェクトには 所有権 (Ownership) が付いています.この所有権には2つの属性があります.

付いています?
二つの属性がある?

( ^ω^)…
0859デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:40:16.86ID:kQOezMEX
「参照」なんて呼んだって中身はただのポインタだから
アドレス値という値を持ってるし、当然その値の所有権もあるし、
&TはCopyで複製される値だし、&mut Tは非Copyでmoveされる値だぞ
0860デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:41:37.97ID:e5dQOFE4
>>853
値と所有者/所有権を切り離して考えるのが無意味なのは正しい
Rustでは値には必ず所有者が存在し、所有者は必ず値を持ち、これが所有権
それぞれ単独では存在できないため、切り離して考えることは無駄で意味がない
0861デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:46:41.92ID:AI6ToQ7h
>>854
何かしらの型の実体という意味で
オブジェクトという言葉を使ってるみたいだよ
値をオブジェクトと言い換えるくらいは可愛いもの
0863デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:50:55.01ID:lvFucdpn
これ推理するの楽しいな

型の反対はオブジェクト
式の反対は値
そうしないと値の反対が二通り存在することになりかねない
0864デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:52:47.93ID:e5dQOFE4
>>859
もちろん参照は実際にはポインタとして登場することが多いけど、必ずしもポインタが登場するわけではなくその保証はない
参照という概念レベルでのみ保証されており、最適化でポインタなんて消えることも多いため、ポインタの存在を仮定してはいけない
もちろん値としての参照がCopy実装型で、可変参照が!Copyなのはその通り
0865デフォルトの名無しさん
垢版 |
2023/02/24(金) 21:54:43.52ID:/RJs/kHR
>>857
自分が見つけられてないだけなら先に謝っておくけど
Rust公式ドキュメントも含めて誰も(値の)所有権という言葉を定義していないように見えるんだ
つまりそんなものは無いんだと今は自分の中で結論している

とか書くと狂人判定されるんだろなあ、もういいけど
0867デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:03:23.59ID:kQOezMEX
>>865
https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html

Ownership Rules
First, let’s take a look at the ownership rules. Keep these rules in mind as we work through the examples that illustrate them:

・Each value in Rust has an owner.
・There can only be one owner at a time.
・When the owner goes out of scope, the value will be dropped.

「所有権」はownershipの訳語だから、このルールにおける「ownerであること」がownershipの定義と言っていいんじゃない?
0868デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:04:46.98ID:e5dQOFE4
>>866
すまんね
そこでポインタをアドレス値と言ってるから、そういう具体的なアドレス値に必ずしも対応するわけではないという説明
もちろん型の分類としてはpointer型でその通り
0869デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:06:26.65ID:e5dQOFE4
>>865
Rust公式本のここが分かりやすい
Ownership Rules
・Each value in Rust has an owner.
・There can only be one owner at a time.
・When the owner goes out of scope, the value will be dropped.
0871デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:12:54.01ID:kQOezMEX
>>868
具体的なアドレス値を利用していない場合に限っては最適化で消えることはあるけど
&Tも&mut Tも取り出したいときには中身のRaw Pointerの具体的なアドレス値を取り出すことはできるんだから
参照にポインタの存在を仮定してもなんの問題もなくない?
0872デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:26:37.20ID:e5dQOFE4
>>871
アドレス値として取り出すこともできるのはもちろんその通り
しかしRustの参照の概念を初心者に教える入門でアドレス値を仮定した教え方は完全に間違いです
0873デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:36:10.73ID:kQOezMEX
Safe Rustの範囲内で raw pointer として中身のアドレス値を取り出すこともできるものを
アドレス値を仮定してはいけないと言われてもお前の個人的思想なんかシラネー
0874デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:42:58.52ID:ifsiIFbz
俺も最初の頃は参照をアドレス値ポインタだと誤解してた
そしてRustではちょっとしたことまでわざわざポインタ経由でアクセスするのかよ無駄だなあと思ってたら
プログラムの生成コードを見るとアドレス値ポインタを使わずにちゃんと処理してた
参照はアドレス値ポインタを仮定しないもっと概念的なものであると今はわかるのうになった
0875デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:43:48.83ID:X6Gu9Bob
むしろC言語の知識があるRust初心者には
「参照はコンパイラが有効性をチェックする安全なポインタ」くらいの方が伝わりやすいと思う
メモリ上に値が保持されるならアドレスは存在するわけだし最適化でメモリにすら乗らないケースの方が特殊でしょ
0876デフォルトの名無しさん
垢版 |
2023/02/24(金) 22:57:52.27ID:ifsiIFbz
参照経由でアクセスしてもポインタ使わずに済むときはポインタ出て来ないから
参照はポインタではなくアドレス値が必要になった時だけポインタになるものじゃないかな
ポインタになる場合も含むもっと上位な概念かな参照は
0877デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:00:37.34ID:kQOezMEX
普通に公式がポインタだっつってんだからポインタなんだよ
お前の脳内ポインタ定義はどうでもええよ
0880デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:12:26.43ID:zZXMvOGK
もうこの言語だいしゅき、ソートアルゴリズムの美しい実装でこだわり過ぎて目の下に幕ができそう♡
0881デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:14:18.16ID:igKefKVx
ポインタ云々より「参照にも所有権がある」と言われたら初心者にとってはわかりにくいでしょ
所有権やそれに関連するルールを概念レベルで説明する際に
不必要に実装の詳細に依存すべきじゃないと思うよ
0882デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:17:10.37ID:E8WzyA/e
このスレだったっけ?
以前クイックソートの実装でHaskellが最も美しいかどうかでレスバしてたのは?
0883デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:19:48.91ID:kQOezMEX
>>881
公式ドキュメントに
・Each value in Rust has an owner.
・All pointers are explicit first-class values.
とあって、 Pointer types のひとつとして References (& and &mut) が紹介されてんだから
参照にも所有権があるのは実装の詳細じゃなくて定義の問題だよ

参照はポインタの一種であり、ポインタは値の一種であり、すべての値にはownerがいるんだよ
公式ドキュメントで、実装ではなく公式ドキュメントでそう定義されてんだよ

最適化でポインタとしての実体が消えるとかいうのこそ実装の詳細に依存した話だよ
0884デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:21:40.39ID:3W5ZdpBM
The bookだと参照はポインタに似てるけどポインタとは違うと書いてあるね

https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
A reference is like a pointer in that it’s an address we can follow to access the data stored at that address; that data is owned by some other variable.
Unlike a pointer, a reference is guaranteed to point to a valid value of a particular type for the life of that reference.
0885デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:27:50.41ID:kQOezMEX
>>884
もっかい貼るけど公式リファレンスね
https://doc.rust-lang.org/reference/types/pointer.html

Pointer types
All pointers are explicit first-class values. They can be moved or copied, stored into data structs, and returned from functions.

References (& and &mut)
(中略)
Copying a reference is a "shallow" operation: it involves only copying the pointer itself, that is, pointers are Copy.

公式リファレンスのIntroductionね
This book is the primary reference for the Rust programming language.

the primary reference って書いてるんだから食い違ったらどっちを参照すべきかわかるよね
0886デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:30:24.61ID:kQOezMEX
A reference is like a pointer in that it’s an address we can follow to access the data stored at that address;

The Book でも参照はアドレスだって言ってんじゃねーか!
0887デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:35:53.64ID:/RJs/kHR
>>867
ではownerの定義はどこに?
何がownerになり得る?
ぱっと見ownerは変数だよと言えそうな気がするけど、temporary valueは束縛されないのでルールの例外になってしまう
MIRレベルだとtemporary valueも変数に束縛される(あってる?詳しくない)ならMIRレベルの変数がownerと言えるかもしれないけど、the Bookごときがそこまで考えて書いてると思う?

さらにRc<T>/Arc<T>はstd docやらnomiconやらで"shared ownership"なる表現を平気で使っていて、
そのOwnership Rulesを絶対視するなら2番目のルールに全力で中指突き立ててることになっちゃう、よね?
もちろんTを共有しているよって意図は自然言語から分かるんだけど、その所有は変数への束縛とはまた別だし、
術語としてのowner/ownershipの定義は曖昧に思えちゃうのよね
0888デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:36:51.47ID:kMIGeBWL
>>885
それはポインタ型だな
参照が実際に受け渡される時は参照値となってポインタ型になるのは当たり前
0889デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:40:22.02ID:igKefKVx
>>883
>・Each value in Rust has an owner.
↑これはThe Bookという初心者向けチュートリアルに書いてある概念レベルの話

>・All pointers are explicit first-class values.
> Pointer types のひとつとして References (& and &mut) が紹介されて
↑これらはリファレンスに書いてある実装レベルの話
後者は言語使用者に現在の実装を正確に伝えるためのもの
前者とは目的も抽象度も違う

The Bookでは参照自体をvalueと呼ぶことを意図的に避けてる
by valueといえば&Tや&mut Tは含まないTを指すように区別して書かれてる
初心者にとってのわかりやすさと実装を反映した説明の正確さを両立できない事情があるから
0890デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:44:20.54ID:lvFucdpn
実装依存の悪口を言うだけの方がじつはわかりやすいんだよね
建設的な造語や新ルールを提案したりしないから
0891デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:45:12.43ID:igKefKVx
>>887
これも同じで初心者にとってのわかりやすさと説明の正確さが両立しないのでお茶を濁してる点
ownerを変数だけに限定してしまうといろいろ困る
‘static &strのownerとか

変数には限られない何かownerという概念的存在がいるんだ!!!ということで理解しといて
0892デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:45:39.79ID:L3ynq/JH
>>883
それは値に所有権があるだけだぜ
そしてそれが参照の時はその本体より長生き出来ないんだから
「参照の所有権」なんて分かりにくい言葉は出す必要がない
それだと>>843
>原本および仮の所有権がすべて放棄された時にオブジェクトは破棄されます.
と発想が同じ
0893デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:46:25.60ID:kQOezMEX
>>889
>↑これらはリファレンスに書いてある実装レベルの話
>後者は言語使用者に現在の実装を正確に伝えるためのもの

お前の妄想は知らねえよ
https://doc.rust-lang.org/reference/introduction.html
This book is the primary reference for the Rust programming language.

現在の実装じゃなくて言語としてのRustについてのリファレンスだよ
0894デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:51:09.77ID:jmHr5CjO
参照はそれが具体的な値としてやりとりされるときはアドレスになるのはわかるけどさ
参照とアドレスを同一視する教え方はよくないね
あまりにも実装寄りの考え方
0897デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:59:46.63ID:kQOezMEX
最適化をかけると生成コード上では実体としてのポインタが消えたり消えなかったりするとか言ってる奴が
リファレンスの定義の話をしてる奴を「あまりにも実装寄り」とか言い出すのギャグだろ
0898デフォルトの名無しさん
垢版 |
2023/02/24(金) 23:59:55.61ID:e5dQOFE4
値の所有権は所有する変数のスコープで尽きるけど、
参照値の所有権は参照先の値より長く生存できない点でちがっていて特殊
だから入門書のそこで参照の所有権という言葉を持ち出すのは混乱の元かな
0899デフォルトの名無しさん
垢版 |
2023/02/25(土) 00:18:09.53ID:KJsK2uHY
>>852
それは突っ込みどころを間違えてる
仮の所有権を参照の所有権と言い換えても
「原本および参照の所有権がすべて放棄された時にオブジェクトは破棄されます.」
となって間違いが悪化してしまう
0900デフォルトの名無しさん
垢版 |
2023/02/25(土) 00:25:30.24ID:ArOrHDqj
>>899
それはそうだね
俺は「仮の所有権」を「参照の所有権」に言い換えろなんて言ってないけどね
0902デフォルトの名無しさん
垢版 |
2023/02/25(土) 00:36:36.63ID:KJsK2uHY
>>900
では言い換えるでもなく訂正するでもなく改善案となっているわけでもなく何をしたかったんだ?
唐突に頭悪いとか言い出すのは異常者か
0903デフォルトの名無しさん
垢版 |
2023/02/25(土) 00:45:57.15ID:ArOrHDqj
>>902
「仮の所有権とか言われても困る」という感想を書きたかったんだよ
訂正や改善案を出したいなら5chじゃなくて著者の問い合わせ先とか出版社の編集部とかでやった方がいいんじゃない?

あと >>901 は別人ね、お前が信じるか信じないかは知らんけど
0904デフォルトの名無しさん
垢版 |
2023/02/25(土) 06:13:10.73ID:nntoePxq
仮の所有権と書かれているのは借用のことを言いたいんだなーってわかる気がする
でもそこで参照の所有権はちょっと違うような違和感
0905デフォルトの名無しさん
垢版 |
2023/02/25(土) 08:48:10.93ID:NS6XQxEK
参照に所有権? それはそれで当然あるやろ
ってとこまで到達してる人と、できていない人
0906デフォルトの名無しさん
垢版 |
2023/02/25(土) 10:57:14.30ID:alhcSVqs
参照することと所有することを区別するのをやめやがったのがJava
これを思い出せる人と記憶がない人の認識がずれてるんじゃないの
0908デフォルトの名無しさん
垢版 |
2023/02/25(土) 11:35:22.59ID:ArOrHDqj
参照型の変数がスコープから外れたらただ単に「参照の値」がドロップされて参照先の値には影響を与えない
という話と
>原本および仮の所有権がすべて放棄された時にオブジェクトは破棄されます.
の記述は普通に関係ある話だけどね
0909デフォルトの名無しさん
垢版 |
2023/02/25(土) 11:42:10.17ID:SzGKc5ny
所有権の複製オジに加えて
仮の所有権オジが出てきて
ある可能性が出てきたな

人類にはRustはまだ早かった説
Rustを正確に使うどころか正確に理解することすら困難だった説
0910デフォルトの名無しさん
垢版 |
2023/02/25(土) 11:48:08.84ID:iCEruD3M
GC言語では参照が生きてる限り参照先が消えないので意味があるけど
Rustで参照の所有権は意味がないよ
0911デフォルトの名無しさん
垢版 |
2023/02/25(土) 11:50:57.14ID:ArOrHDqj
参照型の変数がスコープを外れたら何が起こるかって話だからRustでも意味あるよ
0912デフォルトの名無しさん
垢版 |
2023/02/25(土) 11:51:32.02ID:KWSFcpUq
なんで明らかに理解できてないのにこんな自信満々なんだろうな
正直そのメンタルはほんの少しだけ羨ましいわ
0913デフォルトの名無しさん
垢版 |
2023/02/25(土) 11:59:08.08ID:SzGKc5ny
>>910
意味のあるなしとかいう話かこれ?
参照にも所有権があるっていうだけの単なる事実でしょ
こだわるポイントが頭悪すぎない?
0914デフォルトの名無しさん
垢版 |
2023/02/25(土) 12:28:20.35ID:sdtPy+yt
Rust初心者が参照にも所有権があるんだ!普通の値と同じようにスコープを外れるまで所有権があるんだ!と騒いじゃう気持ちは分かるがもちろん無意味
普通の値ならばブロックスコープを外れるまで移動しない限り所有権があるのはもちろんだが
参照の場合は全く違っていてNLL (Non-Lexical Lifetime)により参照が入っている変数が普通の値なら所有権を持ちつづけている状況でも参照の場合はは無効に成り得る
つまり参照の所有権というものを考えたとしてもその格納されている変数のブロックスコープの間に所有権が保たれる保証はなく参照の所有権を考える意味がないのだ
これが普通の値の所有権との決定的な大きな違い
さらに加えて参照は参照先の生存期間を超えられないルールもあるためこの観点からも参照の所有権を考えても単独存在は出来ず意味がない
したがって参照の所有権なんてことを自慢気に言い出す人はまだRustの基本を理解できていない
0915デフォルトの名無しさん
垢版 |
2023/02/25(土) 12:36:03.27ID:ArOrHDqj
参照についてだけわざわざ所有権に意味があるとかないとか考える意味がない

参照の値は参照先の値よりも先に破棄されなければならない
という追加のルールはあっても、所有権や値にまつわるルールの例外であるわけではない
参照は値のサブセット

すべてのvalueにはownerがいて、ownerがスコープを外れたらdropされる
referenceも例外ではない
0917デフォルトの名無しさん
垢版 |
2023/02/25(土) 13:06:19.39ID:sdtPy+yt
>>916
ライフタイムが終わった時点で所有権も失う
所有権だけ単独で存在し続けられない
0918デフォルトの名無しさん
垢版 |
2023/02/25(土) 13:07:26.55ID:ArOrHDqj
>その格納されている変数のブロックスコープの間に所有権が保たれる保証はなく
コイツ所有権を「アクセスする権利」とかそういう感じで捉えてるのか
仮の所有権おじさんと同類じゃん

ownership って
値に対して ownership を負ってる奴はスコープから外れるときに値をdropしなきゃいけない
って責務の話であってアクセスする権利とかじゃないから保たれる保証がどうとか的外れだよ
0921デフォルトの名無しさん
垢版 |
2023/02/25(土) 13:24:50.91ID:sdtPy+yt
>>918
アクセスする権利なんてひとこも言っていない
妄想で叩き出すのは人として外れている

あと参照&T &mut Tに特別なdrop処理はない
だから参照のdropを考える必要はない
0922デフォルトの名無しさん
垢版 |
2023/02/25(土) 13:34:39.07ID:ArOrHDqj
>>921
アクセスする権利とかそういう類のものじゃないから「所有権が保たれる保証」とか的外れだし

特別なdrop処理があろうがなかろうが値はdropされるし
考える必要がなかろうが参照もownerがスコープをはずれたときにdropされるよ
dropされるのはただの事実だよ、ただの事実なので考える必要があるかないかはどうでもいいよ
0923デフォルトの名無しさん
垢版 |
2023/02/25(土) 13:54:21.62ID:sdtPy+yt
>>922
普通の値の入った変数は他へ移動しない限りブロックの最後まで所有権があることが保証され最後まで自由に使うことができる
参照の入った変数はその参照が使われなくなったら無効となる使い捨てなのでブロックの最後まで所有権がある保証はない
例えばlet a = &T; f(a); let b = &mut T; g(b); let c = &T; の時点でもうaとbは使い捨てされており無効となり使えない
このように参照の場合は普通の値の場合と全く異なる
そして参照は使い捨てされてもdropで何か特別な処理があるわけではないため参照の所有権を考える意味がない
0924デフォルトの名無しさん
垢版 |
2023/02/25(土) 14:11:50.12ID:ArOrHDqj
>>923
>所有権があることが保証され最後まで自由に使うことができる
>無効となる使い捨てなのでブロックの最後まで所有権がある保証はない
>無効となり使えない

・ブロックの最後まで使えるかどうか
・drop時に特別な処理があるかどうか

どちらも所有権の話じゃないね
ownership とは「値の owner がスコープから外れたら値はdropされる」というルールです
そのdrop処理に特別な処理が追加されているかとか、ブロックが終わる前に無効になるとか関係ないです
0925デフォルトの名無しさん
垢版 |
2023/02/25(土) 14:45:07.44ID:bPVO/nT3
参照に限らずCopy型はownership意識する機会が少ないからな
関数に参照の参照(&&T)を渡すみたいな例を考えないと参照値がborrowされた状態を作れない

>>923
「ブロックの最後まで所有権がある保証はない」ってあるけど
仮にブロックの最後で所有権がなくなってるような状況でブロックの最後にその参照を使う処理を追加したときに怒られるのは
ブロックの最後で参照を使った追加箇所じゃなく途中で参照先の値を横取りしようとした部分でしょ
これは「ブロックの最後まで所有権があって最後まで自由に使うことができる」ことにならないかな
0926デフォルトの名無しさん
垢版 |
2023/02/25(土) 14:48:33.46ID:ArOrHDqj
参照をフィールドに含む構造体が入った変数はブロックの最後まで自由に使えることは保証されてないけど所有権あるよね^^;
0927デフォルトの名無しさん
垢版 |
2023/02/25(土) 14:58:04.64ID:sdtPy+yt
>>924
理解できてるけど意固地になっているだけか
参照の場合はNLLでスコープがブロックではない見えないスコープとなり得て使い捨てできるから参照ルールを満たしてる限り前段は自由となるし
後段のdropは何も特別処理がないし
わざわざ参照の所有権を持ち出してくる意味がないことを理解できてるようだな

>>925
そこは明記が不十分で誤解させたようでごめん
参照先の値の所有権ではなく参照自体の話だよ
例えばそこの変数aのこと
0928デフォルトの名無しさん
垢版 |
2023/02/25(土) 15:05:29.21ID:a4UZTu4a
https://doc.rust-lang.org/reference/destructors.html
スコープの定義を探してこのページに来たが、ブロックの途中でmoveされた変数のスコープの終わりはどこなのか
ふつうに解釈するとブロックの終わりのようだが

"When an initialized variable or temporary goes out of scope, its destructor is run, or it is dropped."
これは「スコープを抜けたらdropする」じゃなくて「スコープを抜けたらdropされていなくてはならない」という制約の表現という解釈が正しいのかな
じゃないと二重解放にすることになっちゃう
0929デフォルトの名無しさん
垢版 |
2023/02/25(土) 15:06:07.82ID:ArOrHDqj
>>927
お前が言ってる
・drop時に特別な処理がない
・ライフタイムの制約があり、ブロックの最後まで使える保証がない
は参照だけじゃなくて「参照をフィールドに含むCopy構造体」についても同じ挙動なんだけどね
0930デフォルトの名無しさん
垢版 |
2023/02/25(土) 15:09:11.46ID:sdtPy+yt
>>926
なんだちゃんと基本を理解できていないのか
構造体のフィールドに参照を持たせる場合は構造体にライフタイムパラメータが必要となる
したがって参照をその構造体に入れた後にその参照が使い捨てされた場合(例えば後から可変参照を使う場合)はその使い捨て参照と構造体は運命を共にする
ブロックの最後まで所有権がないことはその構造体にimpl Dropした時だけコンパイルエラーなることから分かる
0931デフォルトの名無しさん
垢版 |
2023/02/25(土) 15:10:49.55ID:ArOrHDqj
>>930
参照をフィールドに含む構造体については普通に所有権を考える意味があるし、
それとまったく同じ挙動である参照についても所有権を考える意味があるね
終わりだね
0932デフォルトの名無しさん
垢版 |
2023/02/25(土) 15:25:48.48ID:a4UZTu4a
>>928
いや、この解釈もだめだ
ローカル変数をmoveで捕捉したクロージャを返す関数は関数のブロックスコープを抜けてもまだdropしちゃいけない
0933デフォルトの名無しさん
垢版 |
2023/02/25(土) 15:27:46.31ID:sdtPy+yt
>>931
え?
参照を所有しても使い捨てになるから参照の所有権を考える意味がない話だぞ
0934デフォルトの名無しさん
垢版 |
2023/02/25(土) 15:34:30.90ID:ArOrHDqj
>>933
スコープを抜けた時に束縛されたdropする責務があることを「所有権を持つ」って言うから
所有権の話にその値が使い捨てかどうかとかライフタイムの制約があるかとか考える意味があるかとか関係ないよ

参照を束縛した変数も、参照を保持する構造体を束縛した変数も、プリミティブ値を束縛した変数も、
drop時に特別な処理があってもなくても、ライフタイムの制約があってもなくても
いずれについても「スコープを抜けた時に束縛されたdropする責務がある」ので所有権はあるよ
意味があるとかないとかどうでもいいよ

参照を束縛した変数も、参照を保持する構造体を束縛した変数も、プリミティブ値を束縛した変数も、
いずれについても「スコープを抜けた時に束縛されたdropする責務がある」ので所有権はあるよ
0938デフォルトの名無しさん
垢版 |
2023/02/25(土) 21:23:46.93ID:qdHk+tio
>>930
ホントにそんなこと起きるのか疑問なので試してみたらマジにそうなった
誰かこうなる仕組みを教えて~

参照をメンバーに持つ構造体で実験
struct Foo<'a> {
x: &'a String,
}

fn main() {
let mut s = String::from("abc");
let mut foo = Foo { x: &String::new() };
foo.x = &s;
println!("{}", foo.x.len());
s.push('0');
println!("{s}");
}
ここまではコンパイルも通り動いた
参照を構造体メンバーに格納した後に
可変参照を利用となるpushをして普通に動いた

そこで書かれてる通りに構造体にDropを実装
impl<'a> Drop for Foo<'a> {
fn drop(&mut self) {}
}
するとコンパイルエラーとなった
つまり参照の所有権は使い捨て(?)とやらで意味がなく(??)
それを持つ構造体はブロックスコープの最後まで生きていないため(???)ということ??
Dropの有無でエラーとなる仕組みがさっぱり分からない
0939デフォルトの名無しさん
垢版 |
2023/02/25(土) 21:45:59.77ID:CalPMh2Z
>>938
dropが実行されるときにxが利用される可能性があるから
s.pushの時点ではfoo.x = &sのimmutable borrowがまだ有効なのでmutable borrowはできませんよ
ということ

Dropがなければs.pushの時点でfoo.x = &sが使われる可能性はもうないから
immutable borrowの期間は終わってるものとして扱える
0940デフォルトの名無しさん
垢版 |
2023/02/25(土) 21:56:28.48ID:CalPMh2Z
>>934
>参照を束縛した変数も、参照を保持する構造体を束縛した変数も、プリミティブ値を束縛した変数も、
>いずれについても「スコープを抜けた時に束縛されたdropする責務がある」ので所有権はあるよ

現実にはスタックポインタをインクリメント/デクリメントするだけなので
挙げられてるような種類の変数にdropする責務や所有権があるかどうかは
初めての人への説明としてわかりやすいかどうかという主観の問題だよね
0941デフォルトの名無しさん
垢版 |
2023/02/25(土) 22:03:39.90ID:qdHk+tio
>>939
ふむむ
参照の所有権は自動的に打ち切られてしまい参照の所有権を考えても意味がないというのは正しいのですか?
impl Drop実装しなければdrop処理は無いと理解していいのですか?
0942デフォルトの名無しさん
垢版 |
2023/02/25(土) 23:40:57.64ID:sdtPy+yt
そうだろ
もちろん>>924の言う通り所有権は「値のownerがスコープから外れたら値はdropされる」というルールは常に適用できる
しかし参照については使い捨てができるためブロックスコープではなくルールを成り立たせるために見えない仮想的なスコープを用意してそこを外れたと考える本末転倒
そしてdropについても何もなされない
だからわざわざ参照の所有権を持ち出して来て考える意味がない
参照で重要なのは所有権ではなくmultiple readers xor single writerルール
0943デフォルトの名無しさん
垢版 |
2023/02/25(土) 23:53:35.45ID:alhcSVqs
しかし、役に立たないことを知りたがる人間の方が
ある知識が役に立つ証拠が不十分と思ったら勉強やめる人間よりも安定しているかもしれない
0945デフォルトの名無しさん
垢版 |
2023/02/26(日) 03:13:20.95ID:7bMwo3Dx
所有権とライフタイムとDropトレイトを全部ごちゃ混ぜにして覚えちゃってる困ったちゃん
0947デフォルトの名無しさん
垢版 |
2023/02/26(日) 10:47:51.71ID:PXNtu1ca
実用レベルの達する前に学習者の9割が脱落してしまう言語
言語がRustだけになるとIT業界は終わる模様
0949デフォルトの名無しさん
垢版 |
2023/02/26(日) 11:13:58.37ID:PXNtu1ca
誤解して入門を終えて実用的なプログラムを書けないで四苦八苦するのは個人の問題だからいい
でも間違った知識のままそれを主張するのは非常に迷惑

ポインターのミスでヒープをぶち壊してるような感覚
0950デフォルトの名無しさん
垢版 |
2023/02/26(日) 11:27:18.64ID:fGMmkE/4
>>947
その時はIT業界とRust業界に分かれるから大丈夫
0952デフォルトの名無しさん
垢版 |
2023/02/26(日) 12:46:50.46ID:bBmvUj++
それでようやく理解できた
参照はdropで何もしないから責務がなくて使い捨てしても構わなくて所有権を考える必要ないと
0954デフォルトの名無しさん
垢版 |
2023/02/26(日) 13:29:31.28ID:sdcrACTy
次スレってワッチョイつけたりしないの?
意図せずともID変わりがちな人もいるし追い辛いからつけてほしい
0955デフォルトの名無しさん
垢版 |
2023/02/26(日) 14:25:35.83ID:dBtzQT39
参照についてだけ""わざわざ""、""特段に""、所有権について ""敢えて意識して""、""所有権について考えないようにする""必要性がない
0956デフォルトの名無しさん
垢版 |
2023/02/26(日) 14:40:14.97ID:/LcclasN
付けてもいいけどたぶんそれだと困る人はワッチョイなしでスレを立てる
そしてそっちが伸びれば誰もワッチョイありスレを使わない
そうしてできた残骸がすでに3スレある

立てたければ勝手にすればいいけど、ワッチョイありスレだけを使い荒らしに反応しない強い意志が求められている
0958デフォルトの名無しさん
垢版 |
2023/02/26(日) 18:37:40.46ID:32xuZUXu
ワッチョイ有無どちらのスレに書き込むかは各自の自由
ワッチョイ無しスレは立てたい人がいればこのスレの後に自由にすればよいが
ワッチョイ有りスレは既に3つもあるため4つ目を立てることは控えた方がよい
0961デフォルトの名無しさん
垢版 |
2023/02/26(日) 20:39:47.94ID:IWkF2kZ0
ワッチョイありが盛り上がってたらそっちに行くって言ってるのに誰も向こうに書かないじゃん
0965デフォルトの名無しさん
垢版 |
2023/02/27(月) 19:38:38.14ID:knW1Dm2b
すまんが、The Bookと比較してオライリー本ってどんな内容になってるの?
0966デフォルトの名無しさん
垢版 |
2023/02/27(月) 21:25:36.59ID:4hfcaKna
The Bookと比較すると
- 図や説明がわかりやすい
- カバーしてる範囲がやや広く説明も詳しめ
- C++との比較がやや多い
- IteratorやStringのメソッドの多くを一つ一つ説明しておりややくどい
- Rust特有のコードの読み方も書いてあって助かった (‘aはティックエーと読む等)

個人的には1点目がすごく大きかった
特にOwnershipとReferenceの章
0967デフォルトの名無しさん
垢版 |
2023/02/27(月) 21:31:00.76ID:qRKv85Qa
オライリー本はRust始めた時に買ったけど一生積んでる
0970デフォルトの名無しさん
垢版 |
2023/03/01(水) 09:54:37.52ID:Nh0mXjrz
Rcって値を所有してるの?
参照だから複数存在できる感じ?
規則と矛盾してて全く分からない
0971デフォルトの名無しさん
垢版 |
2023/03/01(水) 12:37:59.53ID:Avl8k8mO
>>970
同じ値を複数のRCで共有している。

Rustの場合、RCの「参照」は、参照と借用とか参照外しとかの「参照」とは別物と考えたほうが良い。
0972デフォルトの名無しさん
垢版 |
2023/03/01(水) 13:03:01.05ID:450i2TJh
>>970
共同所有

Rc::cloneで新しい共同所有者を追加する
共同所有者がスコープアウトすると共同所有者リスト的なものから削除される
最後の所有者がスコープアウトする際に所有してるポイント先もdropされる
0973デフォルトの名無しさん
垢版 |
2023/03/01(水) 23:42:12.75ID:+2HtVlqv
これを?オペレータ使った書き方するにはどうすればいいですか?
if let [first, second, third] = vec {
...
}
これでは上手く行きませんでした
let [first, second, third] = vec?;
0975デフォルトの名無しさん
垢版 |
2023/03/02(木) 08:11:39.46ID:iXGuMNZc
Rustに限った話じゃないけど低レイヤーに関する情報ってなかなか入手できない
Rustなら一応Embedded Rustがあるけど実践的にはいろいろ足りてない
0977デフォルトの名無しさん
垢版 |
2023/03/02(木) 19:10:50.25ID:OHJUJNoL
>>973
このスレでErr値を使わない時にif letやlet elseを使う、とあったのと同じで
Err値がない場合も同じようにこうする
let [first, second, third] = vec else {
return Err(...); // or None
};

>>975
話が曖昧すぎるので具体的に

>>976
クレイピングは知らん
scraper crateを使っている
0980デフォルトの名無しさん
垢版 |
2023/03/03(金) 00:39:13.95ID:2c4ti5P+
>let [first, second, third] = vec else {
> return Err(...); // or None
>};
vecを直接マッチさせることはできないからsliceにする必要がある

それはいいとしてもvecを固定長のarrayにマッチさせて各要素を異なる名前の変数に入れるかエラーにするやり方はcode smellに感じる
vecが外部入力で変更しようがないのかもしれないがそれでも素直に長さチェックしたほうが良い
0982デフォルトの名無しさん
垢版 |
2023/03/03(金) 01:01:26.40ID:5jfhiVlm
>>980
スライスパターンとそのマッチングはRust公式リファレンスにも載っている普通の便利な用法
わざわざ長さチェックしていたらスライスパターンマッチングを知らない初心者かなと思ってしまう
さらに..パターンも併せて例えば
if let [.., ラス前, _] = s
これも公式に例として出ていて同様に長さチェックは不要
0983デフォルトの名無しさん
垢版 |
2023/03/03(金) 17:46:26.59ID:s0En6Xz7
>>973
moveしたいんなら
let [first, second, third]: [_; 3] = vec.try_into().map_err(|_| MyError::InvalidNumberOfHoge)?;
Vecを[T; N]にtry_intoした場合
Errの型がVecなのでmap_errしないと?が使えない
0984デフォルトの名無しさん
垢版 |
2023/03/03(金) 18:25:09.48ID:hYRwId4B
referenceでも同じ
let [first, second, third]: &[_; 3] = vec[..].try_into().map_err(|_| MyError::InvalidNumberOfHoge)?;
0985デフォルトの名無しさん
垢版 |
2023/03/04(土) 00:46:15.62ID:ksgM7HUQ
結局?を無理に使うよりこの方が短く可読性もいいな
let [first, second, third] = vec[..] else {
return Err(MyError::InvalidNumberOfHoge);
};
0987デフォルトの名無しさん
垢版 |
2023/03/04(土) 21:28:46.68ID:VYEasP1j
ログファイルの各行をsplitして特定の項目(例:日時とIPとURL)だけを拾う処理とかで使えそう
Rustでは書いたことないけど
0989デフォルトの名無しさん
垢版 |
2023/03/04(土) 23:13:10.54ID:Oy3wPidb
>>986はいつもの荒らしだから無視しろ
荒らしは文句をつけるだけで修正案を出さない(出せない)から見分けられる
0990デフォルトの名無しさん
垢版 |
2023/03/06(月) 11:51:11.89ID:tj78G6sJ
>>987
使い捨てのコードじゃなければそういうのはcsv parserやargument parserを使って構造体に変換するからパターンマッチでは書かないよ
0991デフォルトの名無しさん
垢版 |
2023/03/06(月) 12:45:03.92ID:I6GlZboG
それは用途によりけり
構造体にDeserializeする場合もあれば構造体を用意しない場合もある
パース用途以外でマッチングならパーサーが出て来る余地すらない
10011001
垢版 |
Over 1000Thread
このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 53日 0時間 8分 30秒
10021002
垢版 |
Over 1000Thread
5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。


───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────

会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。

▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/

▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php
レス数が1000を超えています。これ以上書き込みはできません。

ニューススポーツなんでも実況