次世代言語23 Go Nim Rust Swift Kotlin TypeScript

■ このスレッドは過去ログ倉庫に格納されています
2021/11/28(日) 16:59:19.16ID:gZqbEyz/
スレタイ以外の言語もok

前スレ
次世代言語22 Go Nim Rust Swift Kotlin TypeScript
https://mevius.5ch.net/test/read.cgi/tech/1629590343/
2022/02/10(木) 19:53:19.62ID:HLYz9uYe
>174
いや、RVOの話じゃなくて、
スタックにあるオブジェクトの所有権を関数呼び出し先に移動するのを
デフォルトにした設計的な意図は何なんだろう
という話。

継続を第一級オブジェクトとしてサポートするのでもなければ
サブルーチンはいずれリターンしてくるんだから、スタックに積んだ
オブジェクトも呼び出し先に所有権を移動しないで持ち続けるのが
自然な感じがするんだよね。
それをわざわざ移動してスタックの奥で破棄する(=スタックに残骸が残る)
ようにしたのはなんでかね、と。
2022/02/10(木) 20:19:32.65ID:rtSKPHyc
>>175
ヒープにあるオブジェクトだと deep copy にコストかかるから shallow copy (move) をデフォルトにして
コストかかる処理はソースコード上明確になるようにしたかったからだと思う
2022/02/10(木) 20:31:58.46ID:HLYz9uYe
>176
Rustもなんだかんだ言ってヒープ使用を想定している、ということかね。
それなら所有権移動をデフォルトにした理由は判る。
2022/02/10(木) 20:36:51.31ID:zC9/cVAd
https://www.reddit.com/r/rust/comments/fa9pkp/what_is_the_motivation_behind_default_move/
このスレで作者が答えているけど、すでに参照を示す&が広く使われてるのにデフォルトを借用にすると、moveを示すために「非参照演算子」みたいなものが必要になって整合性が取れないから、とのこと
あとはスタックにどう置いてどうアクセスするかはコンパイラの最適化の問題であって
言語のセマンティクスとは別、みたいな話も
179デフォルトの名無しさん
垢版 |
2022/02/10(木) 20:48:03.49ID:pZ8EtH2T
>>175
Rustではそんな無駄なことはしていないので大丈夫
まずメソッド定義は以下の3つの方法がある
(1) fn method1(self: Self, 引数)
(2) fn method1(self: &Self, 引数)
(3) fn method1(self: &mut Self, 引数)
Selfは自分の型を示す特別な型であり省略して以下のように略記も可能
(1) fn method1(self, 引数)
(2) fn method1(&self, 引数)
(3) fn method1(&mut self, 引数)
ここで>>175が最初に言っている方法は(1)のケース
参照しか利用しないメソッドなれば(2)のように定義して所有権は移動しない
参照を利用して書き換えるならば(3)のように定義して所有権は移動しない
そして所有権を移動させたいメソッドのみ(1)の定義を用いる
この3つの区別があるためRustでは無駄なことは起きない
2022/02/10(木) 21:34:34.23ID:3aizDYBf
>>174
Rustは所有権がはっきりしてるためコンパイラが安全に最適化をガンガン出来る点が良いな
しかもプログラマーはそれを意識せずにRustのセマンティクスだけ把握して書けば後はコンパイラが勝手に最適化してくれる
これがC/C++だと自分で戻り値の場所を確保して自分でポインタを渡していき競合安全性も含めて自分でメモリ管理しなければならない
CG言語だとスタック上はあきらめてヒープで確保して返して後始末はGC任せ
Rustが有利
2022/02/10(木) 21:40:15.72ID:3aizDYBf
>>178
どちらかに指定が必ず必要なのだから
ライフタイムを管理する必要のある参照の方に&指定する現方法が大正解だな
参照にはsingle writer XOR multi readersのルール義務もあるしな
2022/02/10(木) 21:50:15.02ID:ZN2u8Rs1
ある程度は既存のメジャー言語と作法を揃えないと、タダでさえヤバい学習曲線がさらにとんでもないことになるしねえ
183デフォルトの名無しさん
垢版 |
2022/02/10(木) 22:07:58.55ID:pZ8EtH2T
可変参照と可変じゃない参照の区別が安全性保証の要になっているため
参照の方に記号を付けるのは理に適っている
いずれにしてもC/C++で安全に書く時はそれら含めて意識せざるをえない
それがRustでは様々な点でかなり楽になっているのだからC/C++より学習が大変ということはない
2022/02/11(金) 12:06:27.49ID:vAEawTbN
>>178
なるほどねぇ。
個人的にはconst refを標準にして非参照演算子を用意するのも有りだと思うけど
(変数そのものの状態変更を呼び出し元で明記するという意味で)
そのあたりは作者の設計思想だからなぁ。

ただ、コンパイラの最適化と言語のセマンティクスを切り離すのは単純すぎる気が。
>>180みたいな話もあるんだし。
2022/02/11(金) 12:49:33.03ID:MSfgatap
>>184
参照を返す関数を書いてみればわかる
参照の方が特殊な存在であり記号は何でもよいが記号を付けるべき存在だとわかる
そして適切な記号としては微妙に概念が一部重なるC言語の&を選んだのも適切
2022/02/11(金) 13:38:34.47ID:vAEawTbN
>>185
もともとコールスタック(>>172)の話をしているのに、ヒープデータ前提の参照戻し関数の話をされてもねぇ。
Rustが「効率的にするという約束はしているが、コールスタックとかヒープとかは関係ない」というスタンスなら別だけど。
2022/02/11(金) 13:47:41.99ID:MSfgatap
>>186
ほら理解できていない
まずは実際にプログラミングしてみなさい
ヒープなんか一切用いなくてスタック上しか使わなくても参照返しは必ず起きるしライフタイムの管理が必須となる
2022/02/11(金) 14:39:24.16ID:vAEawTbN
>>187
そこまで言うんだったら具体的なコードを例示してくれない?
「参照返しは必ず起きる」と理解できるような普遍的なコードで頼むよ。
2022/02/11(金) 15:19:57.69ID:HTnX1mLl
>>187
>ヒープなんか一切用いなくてスタック上しか使わなくても参照返しは必ず起きるしライフタイムの管理が必須となる
これは嘘だろ。実際fortranはヒープ使わないし、変数の寿命なんて問題は考えなくて済む。
そういう意味じゃめっちゃ安全。
2022/02/11(金) 16:01:25.44ID:6Qn4bKwU
>>188
数値配列の処理や文字列の処理でよく起きますね
例えばイメージしやすい例だと入力文字列から前置文字列と後置文字列に挟まれた文字列を返す関数
// 【input_str】 = 【prefix_str】 + 【output_str】 + 【postfix_str】
fn get_str_between<'a>(input_str: &'a str, prefix_str: &str, postfix_str: &str) -> Option<&'a str> {
let start_index = input_str.find(prefix_str)? + prefix_str.len();
let end_index = input_str[start_index..].find(postfix_str)? + start_index;
Some(&input_str[start_index..end_index])
}
このように引数に複数の参照が来る時に参照を返す場合はライフタイムの明記をします
この例だと関数が返す参照は引数のinput_strのライフタイムと同じですよと伝えることで
この返り値がさらにどこか別の関数で使われたりあるいは構造体に格納されたりしても出自がわかり安全なわけです

ちなみに文字列処理はヒープエリアを一切使わなくても
スタック上の配列(ex. ArrayString)やstaticエリアだけでも完結できますからその突っ込みは無しでよろしくw
2022/02/11(金) 17:17:31.83ID:vAEawTbN
ああ、データ自体を外部から参照する関数なら参照返しも普通か。>>186自体は間違いだな。

ただ、>>184(参照・実体の表記法/関数呼び出し規則)とはあんまり関係していない気が……やっぱり、Rustの設計思想が>>178だからというのが結論に思えるなぁ。
まあ、このあたりをいじくると、所有権を持つ変数が必ずひとつ存在するRustの設計思想からいじくらなきゃいかんような気がするから、Rustじゃ無理か。
2022/02/11(金) 18:27:07.40ID:6Qn4bKwU
>>191
そこはRust限定の話ではなく一般的な話だと思う
参照というのはあくまでも実体があってこそ生きていられる存在
だから実体を保有する変数がどこかに必ず存在していて
その実体が参照よりも長生きしていないとダングリングポインタになってしまう

(ここからはRustの話)
したがって実体の方を本体として無記号にし
それに依存している存在にすぎない参照の方を&記号で示している
2022/02/11(金) 23:20:00.56ID:3T2kJORw
>>189
すべての関数呼び出しが末尾再帰であれば、呼び出しにあたって現在のスタックフレームを保存する必要はないから、中途半端な
手続き言語で分かった風に語りだす人は、どこかおかしい。コンピューターサイエンスとか齧ったことは無さそう。Rustをやってる人の
こういう語りは言語の発展の邪魔でしかないね
2022/02/11(金) 23:30:45.78ID:6Qn4bKwU
>>193
どうみてもその>>189はRustをわかっていない人がむしろ(デタラメにRustを)批判してるような
2022/02/12(土) 01:31:10.49ID:/iL1/Dd6
Go言語の作者Rob Pike氏が2015年に発表した「Go言語が成功した理由は何なのか?」で
> mapやfilterのような機能は言語の表現力を高めるものであり、 書いていて楽しい言語 に繋がるわけだが、
> これはそのトレードオフとなるメンテナンス性が高く扱いやすい言語という点をを犠牲にするだけでなく、
> (極めて素晴らしい方法で実装しない限り)コンピューターリソースを非常に消費するものだ。
と述べていて当時はその通りに思われてGoでは毎回for文で書くことがシンプルで良いとされてきた
しかしその後Rustのイテレータ実装ではfor文とほぼ同様に速く動かせるようになり
for文で毎回ごちゃごちゃ書くよりメンテナンス性もよく扱いやすいとわかった
2022/02/12(土) 02:24:04.92ID:j7aiOjD7
Rust創造イテレータおじさん。。。
2022/02/12(土) 02:36:04.74ID:/tMtoFMY
どうみても言語の否定じゃなく、どうでも良いようなことを延々と語りだすそいつの思考の人格・性格的否定だろうに。
こんな読解力も何もない奴ばっかか・・・
198デフォルトの名無しさん
垢版 |
2022/02/12(土) 14:28:17.06ID:772ADf0k
>>195
Rust開発者は天才だから仕方ない
2022/02/12(土) 16:13:21.86ID:zOhO24og
所有権という概念を生み出したrustの人(名前わすれた)は天才だよ
効率性と安全性を同時に実現してる
これを関数型言語の人が生み出せなかったのは謎すぎる
2022/02/12(土) 16:49:53.94ID:8ted8XK+
Ruby にはLazy があるから、無限配列でも、iterate できる

実行順序を変える。
書いた通りに前から実行しない
2022/02/12(土) 17:46:20.26ID:Fke1BltY
所有権というかRAIIパターンはC++の方が先でlifetimeの方が独創性あると思う
2022/02/12(土) 18:09:28.52ID:/iL1/Dd6
ライフタイムによって本体だけでなくその参照の正当性まで保証できるようになったわけだ

>>200
Rustのイテレータは受動的に遅延生成だから無限生成もできるけど
勝手に実行順序を変えるようなことはなくプログラマーが書いた通り
203デフォルトの名無しさん
垢版 |
2022/02/12(土) 18:33:27.41ID:zd9UI5Og
>>199
あいつら本当はラムダ計算をしたいのに実現出来なくて仕方なくチューリングマシン考えてる妥協の民だからそんな発想なさそうw
2022/02/12(土) 18:34:57.60ID:gzu2Ubp4
>>199
関数型言語は同一データの共有が極めて多く発生するため、GCなしの実装は実用的ではない
参照透過な言語ならメモリの共有さえしなければいいわけでGCなしの実装は極めて容易だけど、無限のメモリを必要とする
2022/02/12(土) 19:00:19.19ID:gHUJ4QZw
関数型はGCが問題になるような途中過程の実行タイミングのシビアな用途に使われないからってのも大きな理由だと思う
性能面で言えば、ガベージの数が命令形に比べて桁違いに多いからいちいち参照カウントとかやってたらクソ非効率だろうし
2022/02/12(土) 19:37:20.77ID:8ted8XK+
Ruby で普通の繰り返しは、a が無限要素だと、aで止まる

a.b.c
つまり、aの要素数ループ、bの要素数ループ、cの要素数ループの順番

それが、Lazy では、実行順序が変わって、
aの1つ目の要素、bの1つ目の要素、cの1つ目の要素
aの2つ目の要素、bの2つ目の要素、cの2つ目の要素
となる

つまり、aが3要素とすると、a1a2a3・b1b2b3・c1c2c3 が、
a1b1c1・a2b2c2・a3b3c3 に変わる
2022/02/12(土) 21:05:09.08ID:y1lBAL19
>>201
確かに所有権っぽいことならC++でもそれっぽく書けはする
ライフタイムは最初なんじゃこれって思ったけど
我慢して書いてみると見事に"missing piece"を埋めてくれた
2022/02/12(土) 23:41:53.37ID:UjqaVtZ/
我慢して書いてみるって発想は
ルールを守るよりも抜け道を探してそうなハッカーの発想とは対照的だね
2022/02/12(土) 23:51:27.76ID:x20bdFcp
>>206
当たり前のことを書いてるだけじゃん
Rubyではlazy導入で遅延処理となり必要最小限だけをようやく処理できるようになったけど
例えばRustでは最初からそのlazyになっている
だからイテレータを連鎖した時に途中に毎回の無駄な一時配列が生成されることもない
それゆえRustではガベージが途中で生じずスタック領域のみ使用で連鎖でき軽くて速い
2022/02/13(日) 03:57:54.17ID:BBswpWkz
array::mapは複製が生じるだろ、普通はarr.map(...).map(...)は使わないにしてもlazyだから無駄な一時配列が
生成されることもないとか言い過ぎだ。ちゃんとドキュメント読んでんのか?そもそも一時的な集合要素が必要に
なるのはアルゴリズム次第であり、”理解してないのに”信じてしまう事は愚かすぎる
2022/02/13(日) 04:07:23.70ID:8v/TbvES
>>210
array::mapはイテレータじゃないよ
2022/02/13(日) 04:15:35.21ID:BBswpWkz
だから複製生じるでしょ
2022/02/13(日) 04:24:59.24ID:8v/TbvES
array::mapで複製は生じるけどイテレータがlazyか否かの議論には何も関係ないよね
mapはOption::mapなどと同じでイテレータとは関係なくコレクションやコンテナの中身を写像する関数であって、イテレータにも同様の意味を持つ関数が用意されているというだけ

>>209 のイテレータだから無駄なものは作られないは言い過ぎで反例はありそうに自分も思うけど、イテレータじゃないものを持ち出すのは例として適切ではない

イテレータそのもののせいではないが borrow checker のせいで余計なアロケーションが必要になる場合はある
以下の記事の最後の方のコード例なんかが一例
https://fasterthanli.me/series/making-our-own-executable-packer/part-6
2022/02/13(日) 04:25:50.19ID:OAT58Vuo
>>210
array::mapはイテレーターではありません
配列から配列への単なる変換です
| pub fn map<F, U>(self, f: F) -> [U; N] where F: FnMut(T) -> U
arrayでのこの定義を見ればイテレーターではなく返り値の型が配列だとわかるはずです
ちゃんとドキュメントを読みましょう

イテレーターを使えば以下のような例において
Rustでは無駄な一時配列が生成されることはありません
[6, 4, 7, 3, 5, 9, 2, 1, 8]
.iter()
.map(|n| n * n * n)
.filter(|n| n > &300)
.for_each(|n| println!("{n}"))
2022/02/13(日) 04:39:02.47ID:8v/TbvES
<[T ; N] as Iterator>::map() のドキュメントを参照してlazyなことの裏取りをしようとしたら array::map() にたどり着いちゃったのかな
だとしたら rustdoc が分かりづらいのが悪い
2022/02/13(日) 04:44:32.73ID:8v/TbvES
<[T; N] as Iterator> なんて存在しなかった
正しくは
<<[T; N] as IntoIterator>::IntoIter as Iterator>::map
または
<std::slice::Iter as Iterator>::map
だった

こんなの初学者わかんないよね
2022/02/13(日) 04:50:04.12ID:OAT58Vuo
>>213
イテレーター連鎖の途中で「無駄な一時配列が生成されない」は常に正しいです
ただし「そのイテレーターの機能として必要不可欠な無駄ではない」一時配列(Vec)を利用するイテレーターは存在します
いずれにせよ無駄な一時配列が生成されることはありません
2022/02/13(日) 05:06:50.08ID:OAT58Vuo
>>213
そのリンク先の記事を読ませていただきましたが
借用ルール(single writer xor multiple readers)違反が原因でその回避のため途中collect()しているだけでした
具体的には&self.objectsで借用中なのに&mut selfと定義されているself.get_object()を呼び出しています
したがって今回の問題とは無関係ですね
2022/02/13(日) 05:14:01.48ID:8v/TbvES
>>217
「無駄な一時配列」の意味するところがあまり腑に落ちてなかったのだけど、
例えばイテレーターアダプターを呼び出す場合に、全要素列挙して配列で返す方式ではなく、
必要に応じてイテレーターアダプターのIterator::nextが呼ばれて、
さらにその中から元となったIteratorのnext()が呼び出されて...
と、lazyに必要な分だけ呼び出される仕組みになっているということが言いたかったわけね

>>218
はい、イテレータというかborrowの制約なのでlazinessとは関係ない話ですね
2022/02/13(日) 05:43:50.33ID:OAT58Vuo
>>219
Rustの配列(array)はスタック上に置けるようコンパイル時サイズ固定なのはご存知ですよね
したがってイテレーターがもし一時配列を吐くもしくは使おうとすると必然的にサイズ可変のVec利用となりヒープを使うことになってしまいます
ところがRustの標準ライブラリのイテレーターは core::iter::Iterator すなわちcore::はヒープが無い環境でも動作可能を意味します
つまり『Rustの標準ライブラリのイテレーターは一時配列(Vec)を絶対に使わない』ように設計されているのです
一方で外部のライブラリにおいてはデータが全て完全に揃わないと動作できない機能を持つイテレーターの場合に「必要不可欠な無駄ではない一時配列(Vec)」を用いるケースがあります
2022/02/13(日) 15:42:54.09ID:BBswpWkz
で、複製されますよね?
2022/02/13(日) 15:59:57.41ID:qi1oHAf6
上で出ていたこれなら配列は複製されない
Rustはそんな無駄なことはしない

>>214
> [6, 4, 7, 3, 5, 9, 2, 1, 8]
> .iter()
> .map(|n| n * n * n)
> .filter(|n| n > &300)
> .for_each(|n| println!("{n}"))
2022/02/13(日) 16:43:01.35ID:BBswpWkz
そのように書くのはあなたであって"Rustだから"というのは明らかな間違いです。無駄な事をしているのはあなたであってRustではありません
2022/02/14(月) 23:03:20.89ID:T9mSH3bb
Rustのイテレータは他と機能も同じ以上なのにプログラミング言語最速
さらにヒープを使わずOSもないベアメタル環境でも動作可
2022/02/15(火) 17:26:38.96ID:urEpWN+O
実装言語を「Go」から「Rust」に変更、ゲーマー向けチャットアプリ「Discord」
https://atmarkit.itmedia.co.jp/ait/articles/2002/10/news038.html
226デフォルトの名無しさん
垢版 |
2022/02/15(火) 18:02:19.14ID:OW1Pu+wt
>>225
次世代言語スレで2年も前のリンク持ってこられても、、、
2022/02/15(火) 18:08:55.40ID:4VdexSIH
2020年の記事なんですけど
2020年が2年前な訳が無いんですけど
2022/02/15(火) 18:42:09.32ID:Yj0CO5uO
えっ
2022/02/15(火) 19:15:57.25ID:qxt1mofg
2022年だぜ?
2022/02/15(火) 19:37:22.66ID:Q8iyUbNY
時の流れが加速している
2022/02/15(火) 19:44:03.28ID:s9A1ir2/
Rustは言語仕様が汚くライブラリもいまいちなので
同じような概念できれいな文法の言語が欲しい
2022/02/15(火) 20:04:30.75ID:RIp/liSi
>>231
言語仕様が汚くない言語
ライブラリがいまいちじゃない言語

それぞれ例えば何?
2022/02/15(火) 20:39:28.00ID:s9A1ir2/
>>232
言語仕様が汚くない → C言語
ライブラリがいまいちじゃない .net
2022/02/15(火) 21:08:36.63ID:RIp/liSi
レスサンクス
参考になりました(*´∀`*)
2022/02/15(火) 21:46:44.86ID:JEGPyefo
>>233
Cが好きならZigとか良さそうだけどどうなの?
2022/02/15(火) 22:19:13.70ID:s9A1ir2/
>>235
ありがとう
調べてみるよ
2022/02/15(火) 22:22:48.94ID:57mqcwZM
>>231
Rustは言語仕様が洗練されていて綺麗なので気に入った
Option / Result に ? や
match / if let / while let あたり
諸悪の根源の null / nil / undefined などが無くなり清らかになった
2022/02/15(火) 22:24:45.32ID:s9A1ir2/
mutable を mutと書くのがダサく感じる
2022/02/15(火) 22:46:47.98ID:fKsGsq6R
>>225
それ昔話題になっただろ
240デフォルトの名無しさん
垢版 |
2022/02/15(火) 23:21:29.87ID:tssMbTRA
>>227
今年って西暦何年?
2022/02/15(火) 23:21:53.24ID:57mqcwZM
>>238
英語でmutの語感覚ははラテン語mutare(変化する)から来ていて
mutable以外にもpermutationやtransmutationなど変化を感じさせる語源だから良いと思うけど
2022/02/16(水) 13:58:05.68ID:z1zaWa7r
>>237
ここのResult 型の説明で出てくるソースが理解しにくく非常に気持ち悪く汚く見えてしまいます
https://zenn.dev/mebiusbox/books/22d4c1ed9b0003/viewer/bba4b4

これを説明なしでソースだけでパッと流れがわかるなら優秀な人だと思います
243デフォルトの名無しさん
垢版 |
2022/02/16(水) 14:26:20.55ID:ntLj+IC3
>>227
>2020年の記事なんですけど
>2020年が2年前な訳が無いんですけど

言ってることがわからないんだけど。
もしかして異世界からアクセスしてる人か?
2022/02/16(水) 14:54:32.66ID:3pG+9+g8
オッサンの時間の流れは早すぎて、もう2022年になったとは思えない
っていうジョークだろう

もうどうでもいいよ
2022/02/16(水) 16:41:34.23ID:oWbPDf/g
>>242
むしろResult型は美しく大元は数学の圏論のモナドから来ている
HaskellのMaybeモナド = ScalaのOption = RustのOption = 有か無かの二択
HaskellのEitherモナド = ScalaのEither = RustのResult = AかBかの二択
そしてRustではOptionもResultも値格納付きenum(=タグ付きunion)で表現している

RustのResultもEitherと同じくAまたはBの二択にも使えるが
9割以上の使用方法では特に Aを正常値 Bを異常値(エラー値) として用いる
そのため enum型である Result<T,E> は タグOk(T) と タグErr(E) で構成されている
ここで Tは正常値の型T を示し Eはエラー値の型E を示している

つまり Result<T,E> は2つの型を合成して1つの新たな型として扱うことが出来る
これにより様々なエラー処理が非常に簡単となり各演算(and, or, 変換(map), default値)や
Resultを要素とするイテレータの各演算(map, filter, fold, collect)の各Result版を統一的に扱える

単純にエラー時に上位へエラーを伝播させる場合もRustでは単純となる
例えばGo言語では正常値valとエラー値errの多値で返し以下のようになる
 val, err := func()
 if err != nil {
  return err
 }
Rustでは以下の「?」オペレータ1文字追加でよい
 let val = func()?;
ここでfunc()はResultを返しておりそれがエラー値Err(err)の時はその値で即return
そして正常値Ok(val)の時の処理のみに記述コードを専念できる
2022/02/16(水) 18:27:24.16ID:UmvV858q
>>245
そういうレベルの話じゃなくて単にパターンマッチの構文が見慣れないから読みづらいってだけだと思うよ
やってることはファイルをopenしてみて、失敗したらファイルを作成するってだけで何も難しいことはしていないので
2022/02/16(水) 18:59:25.56ID:3pG+9+g8
モダンな言語ならパターンマッチ構文とか当たり前だし、慣れるべきとしか思わんよな
2022/02/16(水) 19:05:31.46ID:9J2Avx3b
んなことはない
switchの中にswitch入れてる不気味なケースと同じで理解の妨げとバグの温床になっている
2022/02/16(水) 19:06:54.11ID:9J2Avx3b
そのうちmatchの中にmatch入れるな見たいなルールが出来て
それが当たり前になるw
2022/02/16(水) 19:08:51.82ID:9J2Avx3b
> Err(ref error) if error.kind() == ErrorKind::NotFound => {
ここが
Err(ref error.kind() == ErrorKind::NotFound) => {

こうなっていない時点でrustは汚い
2022/02/16(水) 19:24:55.51ID:9J2Avx3b
そもそもがさあ
他の言語のライブラリにあるファイルオープン時に指定したファイルがなければ作って開いてくれるようなオプションないのか?
2022/02/16(水) 19:38:23.34ID:J05fEVeY
>>250
それこそクソ構文にしか見えないけど採用してる言語あるの?
Point(x, y) if 0 < x && x < 5 => {
みたいなガード条件書けなくない?
2022/02/16(水) 19:40:31.24ID:9J2Avx3b
C#とかだと複数のプロパティ値を使ったマッチングも当たり前にやっている
2022/02/16(水) 20:09:46.22ID:4BNkCNLv
>>250
Errはenum Resultのタグだからそれは理解が間違っている

>>251
無くても必要なら一瞬で書けるから困らない
例えば関数にするならこのようになる
fn open_or_create(path: impl AsRef<Path>) -> io::Result<File> {
File::open(&path)
.or_else(|err|
if err.kind() == ErrorKind::NotFound {
File::create(path)
} else {
Err(err)
}
)
}
このようにorを使う方が見やすく分かりやすい
matchでOk(x) => x, となったらorと覚えればよい
2022/02/16(水) 20:25:14.55ID:9J2Avx3b
なにかミスってない?
2022/02/16(水) 20:58:53.96ID:bx/iMnwF
C#はここ十年さわってないので分からんけど
> Err(ref error.kind() == ErrorKind::NotFound) => {
みたいに書けるってこと?
そもそもC#にパターンマッチなんかあったやろか?
switchがせいぜいあるだけでは?
あと型もletでdestructできるやつじゃなくて
せいぜい (変数 is 型) でシコシコ調べていくだけでは?
2022/02/16(水) 21:00:56.89ID:UmvV858q
>>250 のkind() は構造体のフィールドとのマッチじゃなくてメソッドの戻り値との比較だから
パターンとして取り扱えるようになるべきではないと思う
構造体のフィールドなら普通にパターンマッチできるよ
2022/02/16(水) 21:07:22.97ID:UmvV858q
>>251
File::options()
.write(true)
.create(true)
.open("hello.txt")
で済む話ではあるから例が微妙というのはあるかもね
2022/02/16(水) 21:19:06.45ID:9J2Avx3b
見返してみると
Err(ref error.kind() == ErrorKind::NotFound)ではなく

Err( ErrorKind::NotFound)
とかけたほうがいいなと
2022/02/16(水) 21:25:48.26ID:9J2Avx3b
上のソースは海外の有名なサイト???からほぼ丸パクリなんだな
そっちも突っ込みどころ満載のソースなんだけどパクったほうはさらにおかしくなってる

変なところだらけ
これとか
let f = File::open("hello.txt");
let f = match f {

それに引き続いたこれ
match File::create("hello.txt") {

そして
Err(e) => panic!("Tried to create file but there was a problem: {:?}", e),

これ
Err(error) => {
panic!("There was a problem opening the file: {:?}", error)
},
2022/02/16(水) 21:30:10.73ID:9J2Avx3b
>>256
ググればわかる
C#はもう全然別物になってるしこれからも変わる予定

誰得?と思うけど
2022/02/16(水) 21:41:12.68ID:oWbPDf/g
>>253
Rustでも複数マッチングは当然できる
例えばorの概念
let v = match (p, q) {
 (true, _) => "前者",
 (_, true) => "後者",
 (_, _) => "失敗",
};

>>255
matchをorで書き換えなら254で合ってる
目的達成だけならoptionsを使う258で合ってる

>>259
そういう単純なエラー型を自分で設計して使うならそれでOK
今回は std::io が返すエラーだから Err(struct io::Error { ...(フィールド非公開) }) となる
つまり Err(err) で受けて err.kind() で種別を取り出すことになる
なぜこうなっているのかは理由があるのでソース std/io/error.rs を読むべし
2022/02/16(水) 21:51:01.16ID:4BNkCNLv
>>260
その変数のシャドーイングも二段階のmatchもpanic!の使用もそれ自体は間違っていない
君は文句をつけることと間違った動かないコードを出すことしかできていない
こちらは改善案として二段のmatchではなくResultをorする>>254というシンプルで動くコードを示した
2022/02/16(水) 23:07:11.77ID:9J2Avx3b
視点がずれてる

変なところが多い=美しくないと言ってるんだけど
意味のあるシャドーイングならわかる
変数使って受けてるのに次ではmatchダイレクト

panicを一行で書いたりブロックをつけて書いたりちぐはぐ

書いた奴は馬鹿なんだろう
2022/02/16(水) 23:09:17.43ID:9J2Avx3b
クソど素人にこれだけ書かれるのは馬鹿なんだろうしそれも理解できないのはどうなんだ?
2022/02/16(水) 23:12:09.22ID:4BNkCNLv
批判だけならバカでもできる
具体的な代案を出せるかどうかが全て
これはどの世界でも同じ
2022/02/16(水) 23:14:11.42ID:9J2Avx3b
いやいや
何を例としてるか全然わかってなかったろ?

具体的に書かれて初めてわかったろ?
そういうところだよ
汚いソースすらわからないんだろ?
2022/02/16(水) 23:18:14.63ID:9J2Avx3b
rust入門サイトにこんなクソみたいなコード乗せるな
Rustの品格が下がる
2022/02/16(水) 23:18:35.44ID:4BNkCNLv
>>267
こちらは具体的な代案を>>254に出した
君は文句をつけるだけで何も生み出せなかった
これが全てだ
2022/02/17(木) 01:06:25.84ID:se607RqK
rustが汚いって話からサンプルコードが汚いって話にすり替わってるな
2022/02/17(木) 08:14:31.32ID:eL25V27g
>>257
>>250は単一化あたりを想定しているんだろ。
本来なら
Err(ref error),
error.kind() == ErrorKind::NotFound

Err(ref error) and
error.kind() == ErrorKind::NotFound
あたりだけど。
2022/02/17(木) 08:14:54.96ID:2OHfN1Ec
もう十分だよ
初心者にありがちな「言語仕様が汚い発言」でしかないのがわかったからもういいよw
2022/02/17(木) 23:22:49.91ID:S7RVNfva
彼は当初Rustの言語仕様が汚いと主張
それが無理筋だとわかると誰か個人が書いたサンプルコードが汚いと主張を変更
ところがそれも修正案すら示せず敗走か
2022/02/18(金) 11:21:48.86ID:TQ4wtLA6
初心者にありがちな発言
「コンパイラのバグ」
「言語仕様が汚い」
「バリバリ書く」
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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