「C++の色々配慮してめんどくさい感じは好きだけど、実務になったらメモリ安全性とか考えて今後Rustに変わっていくんかな」
「うだうだ言ってないで仕事で必要なのをやればいいんだよ、趣味なら好きなのやればいい」
っていう雑談スレ。
結局C++とRustってどっちが良いの? 4traits
https://mevius.5ch.net/test/read.cgi/tech/1686046386/
関連スレ(マ板): Google&MS「バグの70%はC/C++。Rustにする」
https://medaka.5ch.net/test/read.cgi/prog/1619943288/
探検
結局C++とRustってどっちが良いの? 5traits
レス数が950を超えています。1000を超えると書き込みができなくなります。
2023/06/30(金) 21:56:35.52ID:PDIJ4aZy
861デフォルトの名無しさん
2023/07/24(月) 13:30:21.48ID:LicyyNi9862デフォルトの名無しさん
2023/07/24(月) 13:34:38.77ID:DOk3bTYa863デフォルトの名無しさん
2023/07/24(月) 13:36:23.66ID:DOk3bTYa 通信インフラってのは
ソフトウェアの複製がゼロコストなのと違って
コストが掛かるんだよ
ソフトウェアの複製がゼロコストなのと違って
コストが掛かるんだよ
864デフォルトの名無しさん
2023/07/24(月) 13:39:12.35ID:LicyyNi9 >>862
左翼は能力の差まで無視しようとするで。
左翼は能力の差まで無視しようとするで。
865デフォルトの名無しさん
2023/07/24(月) 13:51:35.63ID:DOk3bTYa866デフォルトの名無しさん
2023/07/24(月) 13:59:42.61ID:7fuealYq 自分用には、そこそこ全体がコンパクトな方が好きかなあ
仕事用には、回線も装置も会社のものだから兎も角なんだが
仕事用には、回線も装置も会社のものだから兎も角なんだが
867デフォルトの名無しさん
2023/07/24(月) 14:04:31.32ID:LicyyNi9 「コンパイル速度が遅い」という噂が立ってるんですが、
実際は、crateのダウンロード速度が遅い、ということなんですか?
実際は、crateのダウンロード速度が遅い、ということなんですか?
868デフォルトの名無しさん
2023/07/24(月) 14:05:59.45ID:LicyyNi9869デフォルトの名無しさん
2023/07/24(月) 14:07:33.73ID:1ixoDG3j >>868
例えば? 煽りではなく
例えば? 煽りではなく
870デフォルトの名無しさん
2023/07/24(月) 15:00:19.41ID:056Z4jSG イヤちゃうやろ
流石にそれはコンパイラの作業量が純粋に多いから遅いでしょ
そりゃC++と比べて早くなるわけない
チェックしてる事多いんだから
流石にそれはコンパイラの作業量が純粋に多いから遅いでしょ
そりゃC++と比べて早くなるわけない
チェックしてる事多いんだから
871デフォルトの名無しさん
2023/07/24(月) 15:30:37.55ID:9sf7J+PW >>861
それはプログラム板で主張することじゃないやろ
それはプログラム板で主張することじゃないやろ
872デフォルトの名無しさん
2023/07/24(月) 16:03:16.33ID:7fuealYq C++派だが、C++もたいがい遅いだろ
pchとか使うのが習慣化してるけど
そういや、結構前からmoduleってのが使えるけど、きちんと使ったことないな。。
pchとか使うのが習慣化してるけど
そういや、結構前からmoduleってのが使えるけど、きちんと使ったことないな。。
873デフォルトの名無しさん
2023/07/24(月) 17:44:58.93ID:u3xro2aJ874デフォルトの名無しさん
2023/07/24(月) 18:20:23.66ID:dGeJrBxo 10人必要っぽい場所に20人投入すればいいのに
10人投入してめちゃくちゃになってから10人追加するやつって何なの?
戦力の逐次投入なの?
10人投入してめちゃくちゃになってから10人追加するやつって何なの?
戦力の逐次投入なの?
875デフォルトの名無しさん
2023/07/24(月) 18:51:49.12ID:DOk3bTYa876デフォルトの名無しさん
2023/07/24(月) 21:47:00.51ID:Zw6srC2c877デフォルトの名無しさん
2023/07/24(月) 22:22:14.29ID:dGeJrBxo 自己責任ってあれほど言ったのに
自己とは誰なのか
誰も知らないんだよな
自己とは誰なのか
誰も知らないんだよな
878デフォルトの名無しさん
2023/07/25(火) 01:43:34.89ID:bta56IUp 多次元配列のライブラリの演算スピードがまだnumpyより倍くらい遅い。また、速くできる要素は利便性の観点から悩ましい。rayonを使えばnumpyの倍速くらいにはできるようになった。
879デフォルトの名無しさん
2023/07/25(火) 03:35:47.01ID:w8nK1FpQ880デフォルトの名無しさん
2023/07/25(火) 08:41:35.71ID:UPZxbC6+ スピードが必要な部分だけRustを使わないようにすれば解決
881デフォルトの名無しさん
2023/07/25(火) 08:54:51.87ID:k8WJtY+U そういえば君らのメモリ管理の会話でLinkedListの使い道思い出したわ
Rustやその他の言語側じゃなくてOS側のメモリ管理にLinkedList使われてるわ
Rustやその他の言語側じゃなくてOS側のメモリ管理にLinkedList使われてるわ
882デフォルトの名無しさん
2023/07/25(火) 09:01:07.57ID:k8WJtY+U883デフォルトの名無しさん
2023/07/25(火) 09:02:56.16ID:k8WJtY+U >>880
unsafe {} 便利ですね判ります
unsafe {} 便利ですね判ります
884デフォルトの名無しさん
2023/07/25(火) 09:03:45.28ID:P1fUbQNp まぁ調べてみると確かに行列配列系の計算は“生rust”だと難しいんやろな
でかいデータを高速に捌くには“参照”をうまく使いこなしてなるべく“コピー”の回数を減らすくらいしかアルゴリズムの改善は見込めない
しかしrustは安全性の観点からC++のそれより所有権、生存期間の抽象度、制約を一段引き上げてる
だからそれでも速度が欲しいならunsafeで囲って危ない橋を渡るしかない、実際rcとかarcのソース読むとundafeだらけやしな
逆に言うとユーザーがその“危ない橋”を渡らなくても済むようにライブラリがあるとも言える
でかいデータを高速に捌くには“参照”をうまく使いこなしてなるべく“コピー”の回数を減らすくらいしかアルゴリズムの改善は見込めない
しかしrustは安全性の観点からC++のそれより所有権、生存期間の抽象度、制約を一段引き上げてる
だからそれでも速度が欲しいならunsafeで囲って危ない橋を渡るしかない、実際rcとかarcのソース読むとundafeだらけやしな
逆に言うとユーザーがその“危ない橋”を渡らなくても済むようにライブラリがあるとも言える
885デフォルトの名無しさん
2023/07/25(火) 13:32:44.33ID:cCDBQCCP >>884
ArcやRcは使用はやめた。マルチスレッド化の時にだるいことが多いから。仕方ないのでreshapeメソッドとかでは配列をクローンすることにした。
ArcやRcは使用はやめた。マルチスレッド化の時にだるいことが多いから。仕方ないのでreshapeメソッドとかでは配列をクローンすることにした。
886デフォルトの名無しさん
2023/07/25(火) 13:34:21.22ID:cCDBQCCP あと、行列の計算とかでループのスピードを速くするために次元はconst N: usizeを使ってる。
887デフォルトの名無しさん
2023/07/25(火) 13:51:24.76ID:nk58GX8+ 海外のサイトを見ていたら、Rustは、インクリメンタル
ビルドが遅いらしい。だから、ソースを細かく分けすぎると
遅くなるのかも知れない。しかし、ビルドの高速化の
ために発明されたのがインクリメンタルビルドだった
のだから、本末転倒の厄介な問題だ。
なんでも、リンクに10秒くらいかかるのだとか。
ある人によれば一時間くらいかかったと言う。
ビルドが遅いらしい。だから、ソースを細かく分けすぎると
遅くなるのかも知れない。しかし、ビルドの高速化の
ために発明されたのがインクリメンタルビルドだった
のだから、本末転倒の厄介な問題だ。
なんでも、リンクに10秒くらいかかるのだとか。
ある人によれば一時間くらいかかったと言う。
888デフォルトの名無しさん
2023/07/25(火) 13:53:33.03ID:nk58GX8+ >>887
crateの初回使用の時にフルコンパイルされる
ので遅いのは、それはそれで困るが、ギリギリセーフ
だとしても、それ以上に厄介なのは、自分のソースを
少しいじってビルドしなおしても、リンクはどうしても
必要だから、そこで10秒もかかってしまっては
開発は非常にストレスがかかってしまうことだ。
crateの初回使用の時にフルコンパイルされる
ので遅いのは、それはそれで困るが、ギリギリセーフ
だとしても、それ以上に厄介なのは、自分のソースを
少しいじってビルドしなおしても、リンクはどうしても
必要だから、そこで10秒もかかってしまっては
開発は非常にストレスがかかってしまうことだ。
889デフォルトの名無しさん
2023/07/25(火) 13:58:22.63ID:nk58GX8+ 中くらいの大きさのプロジェクトで、
structの中の一行を変えるだけで、5分かかって
困っていると言う報告も見つけた。
structの中の一行を変えるだけで、5分かかって
困っていると言う報告も見つけた。
890デフォルトの名無しさん
2023/07/25(火) 14:00:01.53ID:uSv6E5ak >>888
リンカーは共通だろうからC/C++と差はないと思うのだが?
リンカーは共通だろうからC/C++と差はないと思うのだが?
891デフォルトの名無しさん
2023/07/25(火) 14:15:10.14ID:nk58GX8+ https://www.reddit.com/r/rust/comments/11vrzme/help_me_love_rust_compilation_time/
Hey all, I've been writing software for about 15 years, Started from VB, .NET (C#), Java, C++, JS (Node), Scala and Go.
I've been hearing about how Rust is great from everyone ! But when I started learning it one thing drove me nuts: compilation time.
Compared to Go (my main language today) I find myself waiting and waiting for the compilation to end.
If you take any medium sized OSS project and compile once, it takes ages for the first time (3,4 minutes, up to 10 !) but even if I change one character in a string it can still take around a minute.
Hey all, I've been writing software for about 15 years, Started from VB, .NET (C#), Java, C++, JS (Node), Scala and Go.
I've been hearing about how Rust is great from everyone ! But when I started learning it one thing drove me nuts: compilation time.
Compared to Go (my main language today) I find myself waiting and waiting for the compilation to end.
If you take any medium sized OSS project and compile once, it takes ages for the first time (3,4 minutes, up to 10 !) but even if I change one character in a string it can still take around a minute.
892デフォルトの名無しさん
2023/07/25(火) 14:31:37.57ID:iTChcdyR cargo 使ってるときに rust にリンカオプション教える方法教えて
893デフォルトの名無しさん
2023/07/25(火) 14:32:50.71ID:nk58GX8+ 海外のサイトを見ていて考えられる要因の候補
・マクロの使いすぎ。Rustのマクロは乱用すると遅いらしい。
・メモリー不足で仮想記憶が働いてしまっている?
・マクロの使いすぎ。Rustのマクロは乱用すると遅いらしい。
・メモリー不足で仮想記憶が働いてしまっている?
894デフォルトの名無しさん
2023/07/25(火) 14:37:55.45ID:nk58GX8+ Rustは、ファイル単位でなく crate 単位でコンパイルするらしい。
だから、あるソースファイルの1行を直してもcrate全体の
コンパイル時間が必要となる。
C++が、ファイル単位でコンパイルするのと対照的となる。
Q: Does Rust compile fast?
A: For incremental builds, Rust will take longer to compile
than C++ (i.e. C++ wins).
This is because Rust compiles one crate at a time,
rather than one file at a time like in C++,
so Rust has to look at more code after each small change.
Jan 5, 2023
だから、あるソースファイルの1行を直してもcrate全体の
コンパイル時間が必要となる。
C++が、ファイル単位でコンパイルするのと対照的となる。
Q: Does Rust compile fast?
A: For incremental builds, Rust will take longer to compile
than C++ (i.e. C++ wins).
This is because Rust compiles one crate at a time,
rather than one file at a time like in C++,
so Rust has to look at more code after each small change.
Jan 5, 2023
895デフォルトの名無しさん
2023/07/25(火) 14:41:52.08ID:MikqYz6X でcrateってのは複数ファイルに跨ることが多いわけ?
それとも1ファイルに複数のcrateが実装されることが多いわけ?
それとも1ファイルに複数のcrateが実装されることが多いわけ?
896デフォルトの名無しさん
2023/07/25(火) 14:49:22.82ID:nk58GX8+ >>895
前者だろう。
前者だろう。
897デフォルトの名無しさん
2023/07/25(火) 14:54:39.48ID:MikqYz6X898デフォルトの名無しさん
2023/07/25(火) 14:55:34.04ID:iTChcdyR create の document の comment coverage てやっぱり判りにくいな
899デフォルトの名無しさん
2023/07/25(火) 17:54:05.55ID:eTFG8/xx Rustもまだまだだなー
Rustを始めるにはまだ早いな(時期が悪いおじさん式
Rustを始めるにはまだ早いな(時期が悪いおじさん式
900デフォルトの名無しさん
2023/07/25(火) 18:01:39.24ID:UOy+ke99 incremental buildはcodegen unit単位
開発者が明示的にリビルドを指示できるのはcrate単位
incremental buildなら変更が不要なcodegen unitはリビルドされない
codegen unitは1モジュールで2つ(non-genericとgeneric)
デフォルトでは1crateにつきcodegen unitの上限は256なのでそれを超えるようならマージされる
モジュール単位なのでファイル単位よりも細かい
開発者が明示的にリビルドを指示できるのはcrate単位
incremental buildなら変更が不要なcodegen unitはリビルドされない
codegen unitは1モジュールで2つ(non-genericとgeneric)
デフォルトでは1crateにつきcodegen unitの上限は256なのでそれを超えるようならマージされる
モジュール単位なのでファイル単位よりも細かい
901デフォルトの名無しさん
2023/07/25(火) 19:11:44.72ID:nk58GX8+ 難しいね。
902デフォルトの名無しさん
2023/07/25(火) 23:14:21.10ID:PfWx6dVw Cの (shared) objectファイルには型情報がない
というかアセンブラの出力と同じ形式にしないとアセンブラを使いにくい
型を無視すればリンクが速い
ヘッダファイルを厳密に管理し、なおかつヘッダを変更しまくれば
C++やRustと似たような遅さになるかもね
というかアセンブラの出力と同じ形式にしないとアセンブラを使いにくい
型を無視すればリンクが速い
ヘッダファイルを厳密に管理し、なおかつヘッダを変更しまくれば
C++やRustと似たような遅さになるかもね
903デフォルトの名無しさん
2023/07/26(水) 03:55:53.44ID:lJlGHJrp ああだから良く判らないcratesが乱立してるのか
cratesに分割すればするほど効率は上がる
crates.ioは氾濫して収拾付かなくなる
cratesに分割すればするほど効率は上がる
crates.ioは氾濫して収拾付かなくなる
904デフォルトの名無しさん
2023/07/26(水) 12:19:34.24ID:kTr42gXw >>902
C++はRustほど遅くない
C++はRustほど遅くない
905デフォルトの名無しさん
2023/07/26(水) 14:36:33.56ID:+VPKYlg4 cast するにも int x から (long long)x でコンパイルされるのと
x: i32 から x as i64 でコンパイルされるのと天と地ほどの時間差がありそう
x: i32 から x as i64 でコンパイルされるのと天と地ほどの時間差がありそう
906デフォルトの名無しさん
2023/07/26(水) 18:02:28.67ID:oS2bmI+b コンパイル時間かかるのは多相型から単相型を導出するとこじゃないの?
907デフォルトの名無しさん
2023/07/26(水) 18:32:17.02ID:JPp8jJPL rust好きだけどJS/TSエコシステム並みにcrateの粒度が小さいのはちょっと厳しいよな。
apacheみたいなのに集約するのはもう時代じゃないんだろうけどさ。
apacheみたいなのに集約するのはもう時代じゃないんだろうけどさ。
908デフォルトの名無しさん
2023/07/26(水) 18:57:07.57ID:jPIzcFjy いつのまにかWindowsでAndroidアプリが動くようになってる
これは便利
これは便利
909デフォルトの名無しさん
2023/07/26(水) 20:27:27.27ID:fbe27uY+910デフォルトの名無しさん
2023/07/27(木) 00:57:46.43ID:as7IkMsZ 型パラメータの候補が複数見つかったらすぐに諦めて競合エラー吐いてる印象
cargo checkだけだと割と軽いからジェネリクスの実体化(コード生成)が重いのかもしれない
型ごとに使ってる処理を割り出して必要な分だけ生成してそうだし
cargo checkだけだと割と軽いからジェネリクスの実体化(コード生成)が重いのかもしれない
型ごとに使ってる処理を割り出して必要な分だけ生成してそうだし
911デフォルトの名無しさん
2023/07/27(木) 02:10:00.11ID:+a559wq5 >>907
私はnumpy並みにデカいパッケージを作ろうと思ってますよ。
私はnumpy並みにデカいパッケージを作ろうと思ってますよ。
912デフォルトの名無しさん
2023/07/27(木) 08:24:40.27ID:mogDSubD >>909
ウソかホントか知らんけど上の方の話だとRustのコンパイルが遅いのはファイル跨ぎの再コンパイルをやらされるからとか
なぜファイル跨ぎの再コンパイルが多発するかといえばやはり多相性の問題じゃないの?
posix系のアーカイバは分割コンパイルを可能とするために関数呼び出しの方法を標準化してる、すなわち呼び出し引数の数と種類が与えられた時、その引数を関数側のローカルスタックに順にセットして呼び出す、そのルールがわかっていれば呼び出し側、呼び出され側は引数の種類と順番がわかっていれば分割してコンパイルできる、たとえはCだとそれを実現するために呼び出し側は関数側の内容全部をしらなくてもよいが引数の種類だけはコンパイラに教えないといけない、それがプロトタイプ宣言
ところが多相型を利用する言語では呼び出し側と呼び出され側の内容が相が多相型だとposix標準ではリンクの方法が定められてないからこのシステムを使う事ができない
なのでHaskellではファイルにまたがる最上位の多相型は明示しないと行けない、明示しない物はコンパイラが勝手に単相化すると言う単相制限(monomorphism restriction)をつけて対処する
一方でRustはその手の制限は設けない、好きにやれと言う立場で単相型決定に必要な“型方程式”に関わるものがファイルを跨いで巨大化する事を禁止しない、その代わりコンパイルが遅くなるのは我慢しろと言う立場なんでしょ?
ウソかホントか知らんけど上の方の話だとRustのコンパイルが遅いのはファイル跨ぎの再コンパイルをやらされるからとか
なぜファイル跨ぎの再コンパイルが多発するかといえばやはり多相性の問題じゃないの?
posix系のアーカイバは分割コンパイルを可能とするために関数呼び出しの方法を標準化してる、すなわち呼び出し引数の数と種類が与えられた時、その引数を関数側のローカルスタックに順にセットして呼び出す、そのルールがわかっていれば呼び出し側、呼び出され側は引数の種類と順番がわかっていれば分割してコンパイルできる、たとえはCだとそれを実現するために呼び出し側は関数側の内容全部をしらなくてもよいが引数の種類だけはコンパイラに教えないといけない、それがプロトタイプ宣言
ところが多相型を利用する言語では呼び出し側と呼び出され側の内容が相が多相型だとposix標準ではリンクの方法が定められてないからこのシステムを使う事ができない
なのでHaskellではファイルにまたがる最上位の多相型は明示しないと行けない、明示しない物はコンパイラが勝手に単相化すると言う単相制限(monomorphism restriction)をつけて対処する
一方でRustはその手の制限は設けない、好きにやれと言う立場で単相型決定に必要な“型方程式”に関わるものがファイルを跨いで巨大化する事を禁止しない、その代わりコンパイルが遅くなるのは我慢しろと言う立場なんでしょ?
913デフォルトの名無しさん
2023/07/27(木) 08:30:54.30ID:+a559wq5 >>912
Rustはライブラリとかのバージョン管理を徹底しているからでない?実際、すべてのライブラリのバージョンはCargo.tomlに明記されてるし、rustのエディションもここに明記されてる。この結果コードの一部を変えただけでもまずCargo.tomlの中身に変更がないかコンパイラが見ないといけない。その後、Cargo.tomlに記載されたライブラリを使ってるすべてののファイルのライブラリ使用に関してチェックしないといけなくなり、これによって少しの変更でもクレート全体の再コンパイルに繋がっているのでは?
Rustはライブラリとかのバージョン管理を徹底しているからでない?実際、すべてのライブラリのバージョンはCargo.tomlに明記されてるし、rustのエディションもここに明記されてる。この結果コードの一部を変えただけでもまずCargo.tomlの中身に変更がないかコンパイラが見ないといけない。その後、Cargo.tomlに記載されたライブラリを使ってるすべてののファイルのライブラリ使用に関してチェックしないといけなくなり、これによって少しの変更でもクレート全体の再コンパイルに繋がっているのでは?
914デフォルトの名無しさん
2023/07/27(木) 08:54:12.15ID:GoQM94Wc >>912
Nimはもっと良いぞ
Nimはもっと良いぞ
915デフォルトの名無しさん
2023/07/27(木) 08:54:59.21ID:xfctCHbO >>913
イヤ、ライブラリのタイムスタンプが違えばとかいうのはCでもC++でも同じ、それで言語間の差はない
C,C++とRust,Monomorphism restriction外したHaskellに差があってコンパイル上の、特に分割コンパイル絡みの差がどこで出てるかの話なんだから
イヤ、ライブラリのタイムスタンプが違えばとかいうのはCでもC++でも同じ、それで言語間の差はない
C,C++とRust,Monomorphism restriction外したHaskellに差があってコンパイル上の、特に分割コンパイル絡みの差がどこで出てるかの話なんだから
916デフォルトの名無しさん
2023/07/27(木) 08:57:49.70ID:4+9enMhq GC無し最速動作のできないNimは論外でスレ対象外
917デフォルトの名無しさん
2023/07/27(木) 09:05:43.60ID:xfctCHbO 一例はお題スレで出てた答え
https://itest.5ch.net/mevius/test/read.cgi/tech/1668333636/969
このfooという関数の型はこのソースだけでは決定できない
呼び出した側がvec<i8>とかvec<i32>とか呼び出した側の要求に応じて初めて単相型が決まる、その時点で初めてスタックに何がどんな順番で積まれるのかが決まる
なのでこの場合posix標準のライブラリ管理の方式では呼び出し側と呼び出され側を別々に分割コンパイルできない
抜粋 (全角スペース使用)
fn foo(input: u32) -> impl Iterator<Item = u32> {
let table: Vec<u32> = bits_iter(input)
.map(|p| 1 << p)
.collect();
(0..(1 << table.len())).map(move |bits| {
bits_iter(bits)
.map(|p| table[p as usize])
.sum()
})
}
https://itest.5ch.net/mevius/test/read.cgi/tech/1668333636/969
このfooという関数の型はこのソースだけでは決定できない
呼び出した側がvec<i8>とかvec<i32>とか呼び出した側の要求に応じて初めて単相型が決まる、その時点で初めてスタックに何がどんな順番で積まれるのかが決まる
なのでこの場合posix標準のライブラリ管理の方式では呼び出し側と呼び出され側を別々に分割コンパイルできない
抜粋 (全角スペース使用)
fn foo(input: u32) -> impl Iterator<Item = u32> {
let table: Vec<u32> = bits_iter(input)
.map(|p| 1 << p)
.collect();
(0..(1 << table.len())).map(move |bits| {
bits_iter(bits)
.map(|p| table[p as usize])
.sum()
})
}
918デフォルトの名無しさん
2023/07/27(木) 09:12:08.48ID:xfctCHbO おっと、この例は中身はu32固定だったな
多相性はiteratorのところだった
まぁ本質同じ、呼び出され側が多相型の場合、呼び出し側の要求と折り合いをどこでつけるのか決定するには両方のソースの型情報が必要、そしてこのような多相型の標準化はposixのライブラリシステムにはない
多相性はiteratorのところだった
まぁ本質同じ、呼び出され側が多相型の場合、呼び出し側の要求と折り合いをどこでつけるのか決定するには両方のソースの型情報が必要、そしてこのような多相型の標準化はposixのライブラリシステムにはない
919デフォルトの名無しさん
2023/07/27(木) 09:14:53.79ID:4+9enMhq >>917
そのfooにジェネリック無いだろ
そのfooにジェネリック無いだろ
920デフォルトの名無しさん
2023/07/27(木) 09:28:11.91ID:4+9enMhq921デフォルトの名無しさん
2023/07/27(木) 09:48:28.92ID:GoQM94Wc >>917-918
ωωω
ωωω
922デフォルトの名無しさん
2023/07/27(木) 10:03:28.53ID:+SEMblDr923デフォルトの名無しさん
2023/07/27(木) 10:12:31.52ID:+SEMblDr924デフォルトの名無しさん
2023/07/27(木) 10:26:22.29ID:8yXVmnx7 だからu32のとこ読み替えてって言ってるやん
925デフォルトの名無しさん
2023/07/27(木) 10:32:44.98ID:xpSIuq71 アレ?
rust の impl trait が返り値に指定されてるのは多相型じゃなかった?
Haskellの
( Num A ) -> [ A ]
とかの糖衣表現でしょ?
上のはstd::iter::Iteratorのtraitのインスタンスは全部取れるんじゃないの?
rust の impl trait が返り値に指定されてるのは多相型じゃなかった?
Haskellの
( Num A ) -> [ A ]
とかの糖衣表現でしょ?
上のはstd::iter::Iteratorのtraitのインスタンスは全部取れるんじゃないの?
926デフォルトの名無しさん
2023/07/27(木) 10:40:56.55ID:xpSIuq71 >>923
そう、この問題を従来のposixのライブラリ管理で無理クリ実現するには関数側が提供できる可能性のある多相型をあらかじめ“全部”用意しといてlinkerが適切な関数を選んでも使うくらいしかない
まあしかしそんな事実際不可能
結局多相型が別ファイルにまたがる場合全ファイルの提供側の多相型と右辺値で現れる制限との型方程式を全部集めて解くしかない
おそらく将来的にはML型の多相型を使う言語全体で多相型の型を分割コンパイルが自由にできるようになるには言語を跨って多相型のインターフェースの規格なりなんなりが定まってこないと無理
当面それは難しいからHaskellはデフォルトで使用禁止、Rustは遅いの我慢しろにしてるんやろ
そう、この問題を従来のposixのライブラリ管理で無理クリ実現するには関数側が提供できる可能性のある多相型をあらかじめ“全部”用意しといてlinkerが適切な関数を選んでも使うくらいしかない
まあしかしそんな事実際不可能
結局多相型が別ファイルにまたがる場合全ファイルの提供側の多相型と右辺値で現れる制限との型方程式を全部集めて解くしかない
おそらく将来的にはML型の多相型を使う言語全体で多相型の型を分割コンパイルが自由にできるようになるには言語を跨って多相型のインターフェースの規格なりなんなりが定まってこないと無理
当面それは難しいからHaskellはデフォルトで使用禁止、Rustは遅いの我慢しろにしてるんやろ
927デフォルトの名無しさん
2023/07/27(木) 10:58:53.97ID:Ak2CsEEh >>925
引数のimpl traitはその関数にとってどんな具体型がやってくるかわからないから多相であり具体型ごとに単相化される
返すimpl traitはその関数にとって具体型が確定しているから多相ではない
引数のimpl traitはその関数にとってどんな具体型がやってくるかわからないから多相であり具体型ごとに単相化される
返すimpl traitはその関数にとって具体型が確定しているから多相ではない
928デフォルトの名無しさん
2023/07/27(木) 11:13:06.60ID:WdhxKs44 >>927
上の例だと返り値は確定してるんですか?
返り値はItem=u32のiterator型なら何でも取れるのでは?
vec<u32>でもLinkedList<u32>でも
呼び出し側の注釈でas vec![u32]なり何なりでいくらでも返り値変えられるのでは?
上の例だと返り値は確定してるんですか?
返り値はItem=u32のiterator型なら何でも取れるのでは?
vec<u32>でもLinkedList<u32>でも
呼び出し側の注釈でas vec![u32]なり何なりでいくらでも返り値変えられるのでは?
929デフォルトの名無しさん
2023/07/27(木) 11:18:43.07ID:WdhxKs44 Item = u32であるIterator traitのインスタンスね
上の例は返り値がItem=u32のiterator traitを持つ任意の型を返り値にとれる
じゃないの?
上の例は返り値がItem=u32のiterator traitを持つ任意の型を返り値にとれる
じゃないの?
930デフォルトの名無しさん
2023/07/27(木) 12:01:34.76ID:GoQM94Wc collect correctly
931デフォルトの名無しさん
2023/07/27(木) 12:03:41.01ID:as7IkMsZ 関数の戻り値が
(0..(1 << table.len()).map(...)
だから戻り値の型はMap<Range<usize>, F<Output = u32>>
(Fはラムダ式の型でコードでは表現できない)
これをimpl Iterator<Item = u32>で代替表記してる
関数の戻り値を変えれば別の型にもできるけど
関数内で分岐して複数通りのIterator実装型を返すのはimpl traitでは無理なはず
(0..(1 << table.len()).map(...)
だから戻り値の型はMap<Range<usize>, F<Output = u32>>
(Fはラムダ式の型でコードでは表現できない)
これをimpl Iterator<Item = u32>で代替表記してる
関数の戻り値を変えれば別の型にもできるけど
関数内で分岐して複数通りのIterator実装型を返すのはimpl traitでは無理なはず
932デフォルトの名無しさん
2023/07/27(木) 12:04:36.92ID:Ak2CsEEh933デフォルトの名無しさん
2023/07/27(木) 12:08:33.21ID:Ak2CsEEh934デフォルトの名無しさん
2023/07/27(木) 12:15:53.12ID:/bGsBsBb でも確かに昔のweb情報見てるとできないって書いてるページあるけど
----
impl Traitは異なる型を返せない
impl Traitは静的ディスパッチなので異なる型を返すことはできません。このコードはコンパイルエラーになります。
fn foo(x: u32) -> impl Iterator<Item=u32> {
if x == 0 {
Some(0).into_iter()
} else {
0..x
}
}
----
https://qiita.com/taiki-e/items/39688f6c86b919988222より
しかし実際上の例ではコンパイル通ってるのでは?
----
impl Traitは異なる型を返せない
impl Traitは静的ディスパッチなので異なる型を返すことはできません。このコードはコンパイルエラーになります。
fn foo(x: u32) -> impl Iterator<Item=u32> {
if x == 0 {
Some(0).into_iter()
} else {
0..x
}
}
----
https://qiita.com/taiki-e/items/39688f6c86b919988222より
しかし実際上の例ではコンパイル通ってるのでは?
935デフォルトの名無しさん
2023/07/27(木) 12:19:18.73ID:/bGsBsBb 具体的に上の例ではIterator<item = u32>は何か単相型に決まってしまうんですか?
[u32]とかvec<u32>とか勝手にコンパイラが決めてしまうんですか?
それ以外の型で使おうとしたらコンパイルできないの?
ホント?
[u32]とかvec<u32>とか勝手にコンパイラが決めてしまうんですか?
それ以外の型で使おうとしたらコンパイルできないの?
ホント?
936デフォルトの名無しさん
2023/07/27(木) 12:45:27.87ID:/bGsBsBb Haskellの例だと下のコードは通ります
https://ideone.com/VQHxZ9
sqTo100 :: ( Enum a, Num a ) => [ a ]
sqTo100 = [ n^2 | n<-[1..10]]
main = do
print $ ( sqTo100 :: [ Int] )
print $ ( sqTo100 :: [ Float] )
5行目ではsqTo100は[Int]型を返す関数として、6行目では[Float]型を返す関数として“臨機応変に”使い分けてくれます
ただしこのような“多相型を返す関数”はPosix標準のLinkerが準拠していないのでHaskellではファイル毎という制限がありますけど
(monomorphism restriction)
rustではできないんですか?
https://ideone.com/VQHxZ9
sqTo100 :: ( Enum a, Num a ) => [ a ]
sqTo100 = [ n^2 | n<-[1..10]]
main = do
print $ ( sqTo100 :: [ Int] )
print $ ( sqTo100 :: [ Float] )
5行目ではsqTo100は[Int]型を返す関数として、6行目では[Float]型を返す関数として“臨機応変に”使い分けてくれます
ただしこのような“多相型を返す関数”はPosix標準のLinkerが準拠していないのでHaskellではファイル毎という制限がありますけど
(monomorphism restriction)
rustではできないんですか?
937デフォルトの名無しさん
2023/07/27(木) 12:47:44.86ID:mFFFavmH 複おじの好きそうな話題
よかったな
よかったな
938デフォルトの名無しさん
2023/07/27(木) 14:12:15.53ID:+SEMblDr >>926
>まあしかしそんな事実際不可能
不可能でない場合も結構多いけども? C++で話をすると
templateパラメータでPOD型しか取り得ない場合は結構ある
POD型なんて限られているので全部明示的インスタンス化しておけば
ビルド時間は短縮できる
>まあしかしそんな事実際不可能
不可能でない場合も結構多いけども? C++で話をすると
templateパラメータでPOD型しか取り得ない場合は結構ある
POD型なんて限られているので全部明示的インスタンス化しておけば
ビルド時間は短縮できる
939デフォルトの名無しさん
2023/07/27(木) 14:38:15.87ID:V6/hbrNj940デフォルトの名無しさん
2023/07/27(木) 14:56:22.32ID:V6/hbrNj 思いっきりガイシュツやった
なんで同じこと何回も聞いてるんだよ
なんで同じこと何回も聞いてるんだよ
941デフォルトの名無しさん
2023/07/27(木) 21:42:00.32ID:x4QyUuiY >>935
関数の戻り型は未定のgeneric parameterを含まなければその関数のコードにより型が一つに定まっている
そしてIteratorは型ではなくtraitなので具体的なtrait実装型が関数のコードにより定まっている
一方で具体的なtrait実装型の中でもparameterとして他の型が含まれると記述が長く指定も面倒になってくる
例えば型parameterに入る他の型にも型parameterが付いて多段になることもよかある
コンパイラはそれらの複雑な指定の具体型を推論で確定できるが人間が記述するのは面倒で可読性も悪い
そのため具体型ではなくimpl traitと具象型を書くことで記述性と可読性を向上できる
関数の戻り型は未定のgeneric parameterを含まなければその関数のコードにより型が一つに定まっている
そしてIteratorは型ではなくtraitなので具体的なtrait実装型が関数のコードにより定まっている
一方で具体的なtrait実装型の中でもparameterとして他の型が含まれると記述が長く指定も面倒になってくる
例えば型parameterに入る他の型にも型parameterが付いて多段になることもよかある
コンパイラはそれらの複雑な指定の具体型を推論で確定できるが人間が記述するのは面倒で可読性も悪い
そのため具体型ではなくimpl traitと具象型を書くことで記述性と可読性を向上できる
942デフォルトの名無しさん
2023/07/27(木) 21:43:40.45ID:x4QyUuiY クロージャは具体型を書くことができない
各クロージャは全て異なる型が自動付与されるがコード上でそれを記述する方法がないためだ
その場合を具象型としてimpl Fn/FnMut/FnOnceを指定できる
各クロージャは全て異なる型が自動付与されるがコード上でそれを記述する方法がないためだ
その場合を具象型としてimpl Fn/FnMut/FnOnceを指定できる
943デフォルトの名無しさん
2023/07/27(木) 23:16:49.96ID:383XGmyH944デフォルトの名無しさん
2023/07/27(木) 23:27:43.84ID:5YX5RIhz 単にジェネリック使えばいいだけだろ
Haskellやっててここまで頭悪いやつ見たの初めてだわ
Haskellやっててここまで頭悪いやつ見たの初めてだわ
945デフォルトの名無しさん
2023/07/28(金) 09:03:31.47ID:3WCp+Y82 このスレは、Rust嫌いな人も集まるスレなんだぞ。
そして、Rustの欠点を書いているのは改良してもらいたいから
ではなく、Rustに退場してもらいたいからだ。
そして、Rustの欠点を書いているのは改良してもらいたいから
ではなく、Rustに退場してもらいたいからだ。
946デフォルトの名無しさん
2023/07/28(金) 10:46:00.43ID:Zgvcm9f5 そ、うそだったのか
947デフォルトの名無しさん
2023/07/28(金) 13:34:05.05ID:plp8L3in >>944
イヤ、上の方で「Rustの返り値にimpl traitをとった場合それがジェネリックにならない理由」を述べてる人いるやん?
それが関数返り値に多相型を取れない理由になるならRustの関数返り値は常に単相型になってしまう、でもそんな事ないでしょつて言ってるんですよ
ともかくRustの説明てそういう理屈に合わない説明をする人かなりいるから困るんですよ
頭わるいのは認めますよ
頭わ悪くてすいません
イヤ、上の方で「Rustの返り値にimpl traitをとった場合それがジェネリックにならない理由」を述べてる人いるやん?
それが関数返り値に多相型を取れない理由になるならRustの関数返り値は常に単相型になってしまう、でもそんな事ないでしょつて言ってるんですよ
ともかくRustの説明てそういう理屈に合わない説明をする人かなりいるから困るんですよ
頭わるいのは認めますよ
頭わ悪くてすいません
948デフォルトの名無しさん
2023/07/28(金) 13:45:48.26ID:/QxH2HMp すいません
結論としてRustでは>>936のような「呼び出し側の都合に合わせて返し値を返す関数」は型変数使って書けば書けるけどimpl traitの書式だと書けない、理由は仕様、でいいんですか?
結論としてRustでは>>936のような「呼び出し側の都合に合わせて返し値を返す関数」は型変数使って書けば書けるけどimpl traitの書式だと書けない、理由は仕様、でいいんですか?
949デフォルトの名無しさん
2023/07/28(金) 13:57:57.50ID:muXw35+Y 総称型と部分型をどっちも単に多相って呼んでるから訳分からなくなってるんでは?
950デフォルトの名無しさん
2023/07/28(金) 14:02:06.50ID:K+Na1vWv951デフォルトの名無しさん
2023/07/28(金) 14:07:57.62ID:muXw35+Y952デフォルトの名無しさん
2023/07/28(金) 14:10:58.16ID:GMHqUp+Z impl traitの中にgenericsの型パラメータ含めればいい
936をRustで実装すると↓みたいになる
(RustにはEnumクラスもNumクラスもないからFrom<u8>で代用してる)
fn iter_sq_to_100<T>() -> impl Iterator<Item = T>
where
T: Copy + From<u8> + std::ops::Mul<Output = T>,
{
(1u8..=10u8).map(|v| {
let t = T::from(v);
t * t
})
}
fn main() {
// 戻り値を受け取る側からTの型を指定
println!("{:?}", iter_sq_to_100().collect::<Vec<u32>>());
println!("{:?}", iter_sq_to_100().collect::<Vec<f32>>());
// 関数を呼び出す側からTの型を指定
println!("{:?}", iter_sq_to_100::<u32>().collect::<Vec<_>>());
println!("{:?}", iter_sq_to_100::<f32>().collect::<Vec<_>>());
}
ただしこれは型パラメータで戻り値が多相的になってるだけでimpl traitでそうなってるわけではない
多相型もジェネリクスも一緒だと思うけどHaskellとの対比だとクラスをBoundに置き換えればいいのかな
936をRustで実装すると↓みたいになる
(RustにはEnumクラスもNumクラスもないからFrom<u8>で代用してる)
fn iter_sq_to_100<T>() -> impl Iterator<Item = T>
where
T: Copy + From<u8> + std::ops::Mul<Output = T>,
{
(1u8..=10u8).map(|v| {
let t = T::from(v);
t * t
})
}
fn main() {
// 戻り値を受け取る側からTの型を指定
println!("{:?}", iter_sq_to_100().collect::<Vec<u32>>());
println!("{:?}", iter_sq_to_100().collect::<Vec<f32>>());
// 関数を呼び出す側からTの型を指定
println!("{:?}", iter_sq_to_100::<u32>().collect::<Vec<_>>());
println!("{:?}", iter_sq_to_100::<f32>().collect::<Vec<_>>());
}
ただしこれは型パラメータで戻り値が多相的になってるだけでimpl traitでそうなってるわけではない
多相型もジェネリクスも一緒だと思うけどHaskellとの対比だとクラスをBoundに置き換えればいいのかな
953デフォルトの名無しさん
2023/07/28(金) 14:40:11.65ID:g7faSWJw >>952
すいません、やっぱりわたしの疑問とは違っています
わたしの理解では「impl traitは引数、返り値に一般型をとるが特定のtrait 境界を持つものを指定する場合の糖衣構文」だと思っていたのです
つまり先の例impl Iterator<Item = u32>であれば
①まず
fn myF(××) -> impl T {...}
の記法でTはtypeではなくてtraitである(ここにtraitが来る事が impl trait 記法の呼び名の理由、この記法は
fn myF(××) -> impl A, where A;T{...}
の糖衣構文で「myFはtrait Tのimplementを持つ任意の型を返す関数」を意味する
と思っていて、よって先の例
fn foo1(input: u32) -> impl Iterator<Item = u32> {...
ではfooはItemがu32であるIterator traitを持つ任意の型を返り値として持てる関数だと思っていました、もちろん自分で好きなクロージャ作ってそれにIterator<Item = u32>をimplementすればそれを返り値に持てると思っているんです
しかしそれは違う、fooは単相型、型は決定しており返り値のサイズも配置も決定しているので分割コンパイルできる(そもそも分割コンパイルの話の中で出てきた話なのでここでの多層性はもちろんこの意味)というツッコミが入ったのでホントかと、もうこのソースでRustはfooの返り値の型を完全に決定してて別のファイルからfooを呼ぶ場合にも別々にコンパイルしてposixの標準のリンカが使えるのかなんてことができるのかと
少なくともHaskellではできないはずです
すいません、やっぱりわたしの疑問とは違っています
わたしの理解では「impl traitは引数、返り値に一般型をとるが特定のtrait 境界を持つものを指定する場合の糖衣構文」だと思っていたのです
つまり先の例impl Iterator<Item = u32>であれば
①まず
fn myF(××) -> impl T {...}
の記法でTはtypeではなくてtraitである(ここにtraitが来る事が impl trait 記法の呼び名の理由、この記法は
fn myF(××) -> impl A, where A;T{...}
の糖衣構文で「myFはtrait Tのimplementを持つ任意の型を返す関数」を意味する
と思っていて、よって先の例
fn foo1(input: u32) -> impl Iterator<Item = u32> {...
ではfooはItemがu32であるIterator traitを持つ任意の型を返り値として持てる関数だと思っていました、もちろん自分で好きなクロージャ作ってそれにIterator<Item = u32>をimplementすればそれを返り値に持てると思っているんです
しかしそれは違う、fooは単相型、型は決定しており返り値のサイズも配置も決定しているので分割コンパイルできる(そもそも分割コンパイルの話の中で出てきた話なのでここでの多層性はもちろんこの意味)というツッコミが入ったのでホントかと、もうこのソースでRustはfooの返り値の型を完全に決定してて別のファイルからfooを呼ぶ場合にも別々にコンパイルしてposixの標準のリンカが使えるのかなんてことができるのかと
少なくともHaskellではできないはずです
954デフォルトの名無しさん
2023/07/28(金) 15:00:21.91ID:GMHqUp+Z 少なくともfooを呼ぶ側はfooの実装とリンクされるまで
返されるimpl traitのサイズも実際の型も分からないから
完全に分割コンパイルが可能とは言えないね
型が分からないと呼ぶべき関数の実装も分からないから標準(?)のリンカは使えない
traitを実装しててその関数が存在することだけは分かるけど
ただfooの戻り値のimpl traitの型は(型パラメータがなければ)
fooの実装側で完全に決定される
「正体が分からない単相型」って感じ
返されるimpl traitのサイズも実際の型も分からないから
完全に分割コンパイルが可能とは言えないね
型が分からないと呼ぶべき関数の実装も分からないから標準(?)のリンカは使えない
traitを実装しててその関数が存在することだけは分かるけど
ただfooの戻り値のimpl traitの型は(型パラメータがなければ)
fooの実装側で完全に決定される
「正体が分からない単相型」って感じ
955デフォルトの名無しさん
2023/07/28(金) 15:13:12.73ID:GMHqUp+Z リンク時に外から型サイズを指定できるオブジェクト形式だと頑張れば分割コンパイル可能なのかな
あまりこの辺は知識がない
あまりこの辺は知識がない
956デフォルトの名無しさん
2023/07/28(金) 15:26:38.94ID:orZ7jJno なんかよう分からないけど、この数日のスレ見てても
imp,trait,whereなど知らない概念が多すぎてRustは難しすぎる。
imp,trait,whereなど知らない概念が多すぎてRustは難しすぎる。
957デフォルトの名無しさん
2023/07/28(金) 15:55:11.46ID:CGNQVLgE958デフォルトの名無しさん
2023/07/28(金) 16:22:37.19ID:cNvH/3YC >>957
間違ってますか?
結論的に
impl Iterator<Item = u32>
を返り値として持つ関数をFile Aで定義して事前コンパイル、その後File Bで独自のIterator <u32> のinstanceを持つ型を作った場合、rust compilorはcompile済みのfile Aをlinkするだけでいいんですか?
間違ってますか?
結論的に
impl Iterator<Item = u32>
を返り値として持つ関数をFile Aで定義して事前コンパイル、その後File Bで独自のIterator <u32> のinstanceを持つ型を作った場合、rust compilorはcompile済みのfile Aをlinkするだけでいいんですか?
959デフォルトの名無しさん
2023/07/28(金) 16:33:53.87ID:2BokdQo2 具体的にはどうするんですか?
file AにはItemとしてどんなサイズの型を指定されるかわからないわけですけどcompilorは各引数を受け取る時スタックのどこに第××引数が格納されてると決定できるんですか?
昔のweb情報では「impl traitが静的にアクセスするアドレスを決定できるように多相な型にするには oxで囲まないとダメ」とありました
Boxedである事を要請すれば確かに事前にアドレスを決定できます
しかし先の例ではBoxedてないので呼び出し側が要求する返り値のサイズが決まっていなければ生でスタックに並べられたら呼ばれた関数は引数を読み出せないんじゃないですか?
もちろん動的に呼び出す時に引数のサイズ与えればできますけどRustはアクセスすべきアドレスをコンパイル時に静的に決定してるんじゃないんですか?
file AにはItemとしてどんなサイズの型を指定されるかわからないわけですけどcompilorは各引数を受け取る時スタックのどこに第××引数が格納されてると決定できるんですか?
昔のweb情報では「impl traitが静的にアクセスするアドレスを決定できるように多相な型にするには oxで囲まないとダメ」とありました
Boxedである事を要請すれば確かに事前にアドレスを決定できます
しかし先の例ではBoxedてないので呼び出し側が要求する返り値のサイズが決まっていなければ生でスタックに並べられたら呼ばれた関数は引数を読み出せないんじゃないですか?
もちろん動的に呼び出す時に引数のサイズ与えればできますけどRustはアクセスすべきアドレスをコンパイル時に静的に決定してるんじゃないんですか?
960デフォルトの名無しさん
2023/07/28(金) 16:45:41.21ID:4cjf/6GX 関数の返し型を具体的に書くかimpl Traitと書くかの違いはもちろん明瞭にある
簡単な例で説明する
// まず実験用のおもちゃ(5ずつ増えるイテレータStepFive)を用意
pub struct StepFive { n: i64 }
impl StepFive {
fn new(init: i64) -> Self { StepFive { n: init } }
pub fn cur_value(&self) -> i64 { self.n } // 注意: イテレータには不要な追加機能
}
impl Iterator for StepFive {
type Item = i64;
fn next(&mut self) -> Option<Self::Item> { self.n += 5; Some(self.n) }
}
// このおもちゃイテレータを返す関数を二つ用意する
// 返し型を具体的に StepFive と書くケース
pub fn step_five_1(init: i64) -> StepFive { StepFive::new(init) }
// 返し型を impl Trait の形で書くケース
pub fn step_five_2(init: i64) -> impl Iterator<Item = i64> { StepFive::new(init) }
fn main() {
// イテレータとしてはどちらも当然機能する
assert_eq!(vec![5, 10, 15], step_five_1(0).take(3).collect::<Vec<_>>());
assert_eq!(vec![5, 10, 15], step_five_2(0).take(3).collect::<Vec<_>>());
// しかしイテレータにない機能を使うと違いが明瞭に出る
assert_eq!(123, step_five_1(123).cur_value()); // コンパイル通る
assert_eq!(123, step_five_2(123).cur_value()); // コンパイルエラー method not found in `impl Iterator<Item = i64>`
}
簡単な例で説明する
// まず実験用のおもちゃ(5ずつ増えるイテレータStepFive)を用意
pub struct StepFive { n: i64 }
impl StepFive {
fn new(init: i64) -> Self { StepFive { n: init } }
pub fn cur_value(&self) -> i64 { self.n } // 注意: イテレータには不要な追加機能
}
impl Iterator for StepFive {
type Item = i64;
fn next(&mut self) -> Option<Self::Item> { self.n += 5; Some(self.n) }
}
// このおもちゃイテレータを返す関数を二つ用意する
// 返し型を具体的に StepFive と書くケース
pub fn step_five_1(init: i64) -> StepFive { StepFive::new(init) }
// 返し型を impl Trait の形で書くケース
pub fn step_five_2(init: i64) -> impl Iterator<Item = i64> { StepFive::new(init) }
fn main() {
// イテレータとしてはどちらも当然機能する
assert_eq!(vec![5, 10, 15], step_five_1(0).take(3).collect::<Vec<_>>());
assert_eq!(vec![5, 10, 15], step_five_2(0).take(3).collect::<Vec<_>>());
// しかしイテレータにない機能を使うと違いが明瞭に出る
assert_eq!(123, step_five_1(123).cur_value()); // コンパイル通る
assert_eq!(123, step_five_2(123).cur_value()); // コンパイルエラー method not found in `impl Iterator<Item = i64>`
}
レス数が950を超えています。1000を超えると書き込みができなくなります。
ニュース
- 高市首相の答弁書に「台湾有事答えない」と明記 存立危機発言当時 ★2 [蚤の市★]
- 米大統領報道官「日本と強固な同盟維持、中国とも協力」 [少考さん★]
- JA全農が「新おこめ券」…来年9月末の有効期限を新設、必要経費のみ上乗せ ★2 [蚤の市★]
- ミス・ユニバース フィンランド代表の「つり目」写真が波紋… 本人釈明も批判やまず 協会謝罪「徹底的に検証」へ [冬月記者★]
- 【テレビ】粗品「THE W」バッサリ「おもんない、レベル低い」審査員就任で「日テレが“血の海”に…」 [湛然★]
- 1人3千円の食品高騰対策、何に使える? あいまいなまま衆院通過 [蚤の市★]
- 【悲報】女さん「ハローワークで仕事を探してる3-40代の中年男性いるでしょ。あれ何?」 [483447288]
- キ...キャ...キャ...キャン...
- 彼女とエッチして寝て朝立してたらどうすんの?
- 【悲報】維新の政治資金でガールズバー、高市首相「良いか悪いかは国民の皆さまが判断されること」 [115996789]
- 中国人、ガチ超正論。「日本人がアイヌに対してやったことを『問題ない』とするなら、中国が日本人に同じことをしても文句ないだろう?」 [314039747]
- お前ら「冬のボーナス」なんぼだった?
