「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
レス数が1000を超えています。これ以上書き込みはできません。
2023/06/30(金) 21:56:35.52ID:PDIJ4aZy
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>`
}
961デフォルトの名無しさん
2023/07/28(金) 16:46:14.77ID:4cjf/6GX >>960の続き
つまり返し型を具体的に StepFive と書けばその型の機能をフルに活用できる
しかし返し型を impl Iterator<Item = i64> と書けばイテレータとしての機能のみが使える
後者はコンパイル時に StepFive の実装を知る必要がなくなる
つまり後者は next() で Option<i64> が返るという「impl Iterator<Item = i64>」の一般的知識のみでコンパイルできることになる
その代わり後者は StepFive にcur_value() というイテレータとは別のメソッドがあっても使えないという違いが出てくる
つまり返し型を具体的に StepFive と書けばその型の機能をフルに活用できる
しかし返し型を impl Iterator<Item = i64> と書けばイテレータとしての機能のみが使える
後者はコンパイル時に StepFive の実装を知る必要がなくなる
つまり後者は next() で Option<i64> が返るという「impl Iterator<Item = i64>」の一般的知識のみでコンパイルできることになる
その代わり後者は StepFive にcur_value() というイテレータとは別のメソッドがあっても使えないという違いが出てくる
962デフォルトの名無しさん
2023/07/28(金) 16:49:54.59ID:GMHqUp+Z963デフォルトの名無しさん
2023/07/28(金) 17:13:12.78ID:CGNQVLgE964デフォルトの名無しさん
2023/07/28(金) 17:40:24.39ID:sn3bIpOK >>962
>C++20もconceptとかrequireとか言い出してるから心配しなくていいよ
最近のC++に問題が多数混入したことは知られているが、
人気が絶頂だったころのC++はシンプルで分かり易かったぞ。
>C++20もconceptとかrequireとか言い出してるから心配しなくていいよ
最近のC++に問題が多数混入したことは知られているが、
人気が絶頂だったころのC++はシンプルで分かり易かったぞ。
965デフォルトの名無しさん
2023/07/28(金) 17:59:52.30ID:gdkptAW0966デフォルトの名無しさん
2023/07/28(金) 18:02:55.59ID:GMHqUp+Z 人気が絶頂だったころのC++っていつのC++だ
C++17あたりかな
まさかC++98とは言わんよな…(当時は言語の選択肢が少なかったと思うけど)
C++17あたりかな
まさかC++98とは言わんよな…(当時は言語の選択肢が少なかったと思うけど)
967デフォルトの名無しさん
2023/07/28(金) 18:26:18.74ID:sn3bIpOK C++98位が絶頂。
968デフォルトの名無しさん
2023/07/28(金) 19:04:47.55ID:Ih8SBU9O >>956
流石にそれはRustへの知識が足らんだろ。impl, trait, whereは全てRustでは必要不可欠な概念だぞ。ここら辺がわかってないとなると構造体に関する理解も怪しいだろ。
流石にそれはRustへの知識が足らんだろ。impl, trait, whereは全てRustでは必要不可欠な概念だぞ。ここら辺がわかってないとなると構造体に関する理解も怪しいだろ。
969デフォルトの名無しさん
2023/07/28(金) 19:33:09.89ID:sn3bIpOK >>968
でも覚えたくないから。
でも覚えたくないから。
970デフォルトの名無しさん
2023/07/28(金) 20:29:08.19ID:rzH+uNMJ >>956
traitの概念と用法だけ覚えればよくてimplとwhererは一般的な言葉と同じ
implは単なる「実装」
「impl Trait」が型指定の位置に来れば「Traitを実装」している型の意味
「impl Trait for 型」は「その型にTraitを実装」宣言
「impl 型」は「その型を実装」宣言
whereは説明を後置する関係副詞と同じ
型に対してtraitによる境界(制約)などを指定
traitの概念と用法だけ覚えればよくてimplとwhererは一般的な言葉と同じ
implは単なる「実装」
「impl Trait」が型指定の位置に来れば「Traitを実装」している型の意味
「impl Trait for 型」は「その型にTraitを実装」宣言
「impl 型」は「その型を実装」宣言
whereは説明を後置する関係副詞と同じ
型に対してtraitによる境界(制約)などを指定
971デフォルトの名無しさん
2023/07/28(金) 20:33:57.60ID:rDj5FSnq >>967
そっからは…JavaScriptなんかが本気で伸びていった時期か。
そっからは…JavaScriptなんかが本気で伸びていった時期か。
972デフォルトの名無しさん
2023/07/28(金) 23:59:27.11ID:GMHqUp+Z C++アンチの大半はC++98を嫌々使ってた世代だろ
C++0xが16進数のBになるとは思わなかった
C++0xが16進数のBになるとは思わなかった
973デフォルトの名無しさん
2023/07/29(土) 02:08:00.81ID:MBm8IaU2 ポコチンファイト
974デフォルトの名無しさん
2023/07/29(土) 03:40:53.45ID:yFHJJQio C++は、98年頃、非常に人気であった。
それが、どんどん人気を失い、現状に至っている。
それが、どんどん人気を失い、現状に至っている。
975デフォルトの名無しさん
2023/07/29(土) 05:56:52.93ID:oT83Ayc0 人気があったのはあくまでc とかの古い言語に対してだろ。
当時もperl5とかのスクリプト言語の方が人気だったし。
当時もperl5とかのスクリプト言語の方が人気だったし。
976デフォルトの名無しさん
2023/07/29(土) 10:55:11.31ID:m3e/8XSV >>965
its true👍
its true👍
977デフォルトの名無しさん
2023/07/29(土) 12:15:13.32ID:mCbo+dID >>975
C++は、C++11以後、改悪された。
C++は、C++11以後、改悪された。
978デフォルトの名無しさん
2023/07/29(土) 12:34:34.52ID:XwXxiU6u979デフォルトの名無しさん
2023/07/29(土) 12:37:22.94ID:mCbo+dID C++以後とはC++11自体も含む。
C++11が改悪の最初。
C++11が改悪の最初。
980デフォルトの名無しさん
2023/07/29(土) 12:42:47.89ID:mCbo+dID C++11が最良と思っている人はC++が最悪の言語に
見えることだろう。そしてそういう人がRustを礼賛
しているように見える。
ちなみに、Stackoverflow の Most Loved Language
は、実際に使用した上で好き嫌いを表明した人を分母
とした上での好きな人の比率に過ぎないので、
たとえば、
C++ : 好き=50:嫌い=50, 愛され率 50%
Rust : 好き=7:嫌い=3, 愛され率 70%
のようになっているに過ぎない。
この場合、C++好きはRust好きの7倍以上居るが、
比率的には愛され率が50%になってしまって、
Rustより愛されて無い、という結果になってしまうが
それは統計上の一応の数値に過ぎない。
見えることだろう。そしてそういう人がRustを礼賛
しているように見える。
ちなみに、Stackoverflow の Most Loved Language
は、実際に使用した上で好き嫌いを表明した人を分母
とした上での好きな人の比率に過ぎないので、
たとえば、
C++ : 好き=50:嫌い=50, 愛され率 50%
Rust : 好き=7:嫌い=3, 愛され率 70%
のようになっているに過ぎない。
この場合、C++好きはRust好きの7倍以上居るが、
比率的には愛され率が50%になってしまって、
Rustより愛されて無い、という結果になってしまうが
それは統計上の一応の数値に過ぎない。
981デフォルトの名無しさん
2023/07/29(土) 12:56:18.62ID:XwXxiU6u982デフォルトの名無しさん
2023/07/29(土) 12:56:58.78ID:mCbo+dID 新しいものが良いものだという固定観念は間違い。
C++は、C++98が最良で、C++11で改悪されごちゃごちゃに
なった。
C++を愛する人はC++98を愛した人。
C++11以後を見ると改悪された後なのでごちゃごちゃになった
醜態を見る事になり、C++が大嫌いになる。
そして、そういう人がC++を完全に避けるようになり、行き場所を
失い、Rustを礼賛している。
C++は、C++98が最良で、C++11で改悪されごちゃごちゃに
なった。
C++を愛する人はC++98を愛した人。
C++11以後を見ると改悪された後なのでごちゃごちゃになった
醜態を見る事になり、C++が大嫌いになる。
そして、そういう人がC++を完全に避けるようになり、行き場所を
失い、Rustを礼賛している。
983デフォルトの名無しさん
2023/07/29(土) 12:58:15.78ID:XwXxiU6u984デフォルトの名無しさん
2023/07/29(土) 12:58:56.51ID:mCbo+dID >>981
moveは、std::vectorをメインコンテナに位置づけたから
必要となった概念に過ぎない。LinkedListをメインコンテナ
にすれば、不要となる。そして、ここでいうLinkedListとは
本来のLinkedListの事であり、std::listのことでない。
C++委員会は馬鹿ばっかっりなので、本来のLinkedList
を全く理解できて無い。
moveは、std::vectorをメインコンテナに位置づけたから
必要となった概念に過ぎない。LinkedListをメインコンテナ
にすれば、不要となる。そして、ここでいうLinkedListとは
本来のLinkedListの事であり、std::listのことでない。
C++委員会は馬鹿ばっかっりなので、本来のLinkedList
を全く理解できて無い。
985デフォルトの名無しさん
2023/07/29(土) 12:59:13.66ID:XwXxiU6u >>982
moveなしのC++なんよく使う気になるね
moveなしのC++なんよく使う気になるね
986デフォルトの名無しさん
2023/07/29(土) 12:59:23.06ID:mCbo+dID987デフォルトの名無しさん
2023/07/29(土) 13:01:23.60ID:mCbo+dID >>985
数学や右脳的IQが低い人にはLinkedListは理解が難しい
概念とされているため、LinkedListを使わない人に
とって、moveは必須となってしまうが、バグの温床と
なっている。
そのために出てきたのがRust。
何もかもが間違っている。
数学や右脳的IQが低い人にはLinkedListは理解が難しい
概念とされているため、LinkedListを使わない人に
とって、moveは必須となってしまうが、バグの温床と
なっている。
そのために出てきたのがRust。
何もかもが間違っている。
988デフォルトの名無しさん
2023/07/29(土) 13:02:06.55ID:XwXxiU6u >>984
>moveは、std::vectorをメインコンテナに位置づけたから
>必要となった概念に過ぎない。
違うだろwww
std::vectorの高速化にも役立つが
vectorのために作られた概念では断じてない
>moveは、std::vectorをメインコンテナに位置づけたから
>必要となった概念に過ぎない。
違うだろwww
std::vectorの高速化にも役立つが
vectorのために作られた概念では断じてない
989デフォルトの名無しさん
2023/07/29(土) 13:03:53.63ID:XwXxiU6u990デフォルトの名無しさん
2023/07/29(土) 13:06:10.18ID:XwXxiU6u991デフォルトの名無しさん
2023/07/29(土) 13:09:29.91ID:XwXxiU6u この人の行動パターンは新しいことを学習することを極度に嫌うんだな
それ自体は当人の自由だが
「俺が覚えたくない新しいことは間違ってるのでおまいらも覚えるな
おまいらは馬鹿だ」って考え方はどうなのよ?
それ自体は当人の自由だが
「俺が覚えたくない新しいことは間違ってるのでおまいらも覚えるな
おまいらは馬鹿だ」って考え方はどうなのよ?
992デフォルトの名無しさん
2023/07/29(土) 13:10:49.76ID:mCbo+dID はっきりいって、std::vectorとそれに類するデータ構造
以外では、moveはほとんど役立ってない。
以外では、moveはほとんど役立ってない。
993デフォルトの名無しさん
2023/07/29(土) 13:11:57.95ID:mCbo+dID もちろん、意味が有るケースもあるが、コンピュータでは、
「率」が重要となる。
重箱の隅をつつくような事を重視して、優先順位の高い
ことを疎かにすれば、良い結果にはならない。
「率」が重要となる。
重箱の隅をつつくような事を重視して、優先順位の高い
ことを疎かにすれば、良い結果にはならない。
994デフォルトの名無しさん
2023/07/29(土) 13:15:00.69ID:mCbo+dID コンピュータの世界では何かの概念を導入すると、
必ずと言っていいほど、別の何かとはトレードオフに
なってしまう。
だから、優先順位や使用率、遭遇率、出現確率などを
常に考慮し続けなければならない。
その配慮に欠けているのが(C++11も含む)C++11以後。
そして、Rustは優先順位が間違ったC++11の悪いものを改良して
しまったから、汚い最悪の言語となってしまっている。
センスの悪い言語と言える。
必ずと言っていいほど、別の何かとはトレードオフに
なってしまう。
だから、優先順位や使用率、遭遇率、出現確率などを
常に考慮し続けなければならない。
その配慮に欠けているのが(C++11も含む)C++11以後。
そして、Rustは優先順位が間違ったC++11の悪いものを改良して
しまったから、汚い最悪の言語となってしまっている。
センスの悪い言語と言える。
995デフォルトの名無しさん
2023/07/29(土) 13:39:52.19ID:XwXxiU6u996デフォルトの名無しさん
2023/07/29(土) 13:41:30.10ID:XwXxiU6u997デフォルトの名無しさん
2023/07/29(土) 13:44:38.55ID:XwXxiU6u998デフォルトの名無しさん
2023/07/29(土) 13:51:09.21ID:5uFTVg8T その人small oの意味間違ってた人?
あの数学力見るととても言ってるほど賢いと思えない
あの数学力見るととても言ってるほど賢いと思えない
999デフォルトの名無しさん
2023/07/29(土) 14:01:34.25ID:mCbo+dID >>998
俺はそんな間違いはしない。別人だろう。
俺はそんな間違いはしない。別人だろう。
1000デフォルトの名無しさん
2023/07/29(土) 14:04:41.52ID:mCbo+dID >>997
手短に言えば、本来の使い方をするためのインターフェースだな。
手短に言えば、本来の使い方をするためのインターフェースだな。
10011001
Over 1000Thread このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 28日 16時間 8分 6秒
新しいスレッドを立ててください。
life time: 28日 16時間 8分 6秒
レス数が1000を超えています。これ以上書き込みはできません。
ニュース
- 米大統領報道官「日本と強固な同盟維持、中国とも協力」 [少考さん★]
- ミス・ユニバース フィンランド代表の「つり目」写真が波紋… 本人釈明も批判やまず 協会謝罪「徹底的に検証」へ [冬月記者★]
- 【おこめ券】鈴木憲和農相 小泉前農相の備蓄米放出を“反省”「備蓄の円滑な運営を図ってまいります」 [Hitzeschleier★]
- 1人3千円の食品高騰対策、何に使える? あいまいなまま衆院通過 [蚤の市★]
- ゆたぼん 二重手術を報告「めちゃくちゃ気に入っています」 [muffin★]
- 【27歳会社員】「自慰行為に使うために」コインランドリーの乾燥機から24歳女性の下着など計11点(時価8万2080円相当)盗んだ疑い [nita★]
