公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust
Web上の実行環境
https://play.rust-lang.org
日本語の情報
https://rust-jp.rs/
※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/
※C++との比較は専用スレへ
C++ vs Rust
https://mevius.5ch.net/test/read.cgi/tech/1619219089/
※次スレは原則>>980が立てること
前スレ
Rust part13
https://mevius.5ch.net/test/read.cgi/tech/1636247099/
探検
Rust part14
■ このスレッドは過去ログ倉庫に格納されています
2022/02/12(土) 01:24:16.59ID:XYE+Rws6
602デフォルトの名無しさん
2022/04/06(水) 10:33:16.53ID:Dw8vI7FQ603デフォルトの名無しさん
2022/04/06(水) 11:49:10.11ID:rSNzLcDe604デフォルトの名無しさん
2022/04/06(水) 17:06:15.48ID:SXJV6JXP >>601
なるほど、クロージャにすれば?使えるって発想なかったわ
なるほど、クロージャにすれば?使えるって発想なかったわ
605デフォルトの名無しさん
2022/04/06(水) 18:11:52.43ID:9SYtmHqH なるほどじゃねーよwww
606デフォルトの名無しさん
2022/04/07(木) 04:17:47.69ID:tEZE72Zs stableでどうしてもtryっぽく書きたい場合の苦肉の策でしかないな
607デフォルトの名無しさん
2022/04/07(木) 07:08:56.80ID:GJZ5/Xn8 クロージャ(ラムダ)の即時実行は他の色々な言語でも行なう頻出パターン
Rustでは他にもforやwhileから値を返したい時などにもクロージャの即時実行で行なう
Rustでは他にもforやwhileから値を返したい時などにもクロージャの即時実行で行なう
608デフォルトの名無しさん
2022/04/07(木) 07:19:00.45ID:M1TIObhS これって、公開するメソッドのの数だけディスパッチャメソッドが増えてく感じなの?
https://tourofrust.com/81_ja.html
結構めんどくさいような気もするんだけど・・・・こういうのってエディタの拡張とかが勝手やってくれたりとか、支援みたいなのあるの???
https://tourofrust.com/81_ja.html
結構めんどくさいような気もするんだけど・・・・こういうのってエディタの拡張とかが勝手やってくれたりとか、支援みたいなのあるの???
609デフォルトの名無しさん
2022/04/07(木) 07:36:57.92ID:GySucWIC >>608
プログラマーは全く何もしなくてよい
dyn Traitの場合はメソッド数分の関数ポインタを持つディスパッチ用テーブルが各使用型毎に自動的に生成されて実行時に自動的に適用される
impl Traitの場合は使用メソッドの関数がモノモーフィゼーションすなわち各使用型毎にコンパイル時に展開される
逆にプログラマーが自分で分岐処理する第三の方法としてenumに各使用形を収容してmatchによる分岐処理があってこの方法が有利になるケースもある
プログラマーは全く何もしなくてよい
dyn Traitの場合はメソッド数分の関数ポインタを持つディスパッチ用テーブルが各使用型毎に自動的に生成されて実行時に自動的に適用される
impl Traitの場合は使用メソッドの関数がモノモーフィゼーションすなわち各使用型毎にコンパイル時に展開される
逆にプログラマーが自分で分岐処理する第三の方法としてenumに各使用形を収容してmatchによる分岐処理があってこの方法が有利になるケースもある
610デフォルトの名無しさん
2022/04/07(木) 10:32:38.29ID:bzCO3d2+ C++ だと静的な多相はテンプレートで、動的な多相は仮想関数 (抽象クラス) でやってるわけだけど、
Rust だと dyn だけで切り替えられるってわけだな。
Rust だと dyn だけで切り替えられるってわけだな。
611デフォルトの名無しさん
2022/04/07(木) 12:45:48.26ID:Qjh8kwCx612デフォルトの名無しさん
2022/04/07(木) 13:22:38.91ID:bzCO3d2+ わかる。
Rust の型システム・所有権システムは理屈が分かってないと慣れでどうにかなるもんではない。
理解した上でなら手を動かしてみるのは悪くないと思うけど。
Rust の型システム・所有権システムは理屈が分かってないと慣れでどうにかなるもんではない。
理解した上でなら手を動かしてみるのは悪くないと思うけど。
613デフォルトの名無しさん
2022/04/07(木) 15:06:14.55ID:pUyNlzjX614デフォルトの名無しさん
2022/04/07(木) 18:17:40.12ID:6J24GmAj >>607
クロージャの即時呼び出しは基本的に言語機能が足りない場合のワークアラウンドでしょ
クロージャの即時呼び出しは基本的に言語機能が足りない場合のワークアラウンドでしょ
615デフォルトの名無しさん
2022/04/07(木) 18:20:36.61ID:6QFUvNfL クロージャは引数と戻り値を推論してくれるからこそだね
関数でも、なんかの条件付きでもいいから推論してほしいわ
関数でも、なんかの条件付きでもいいから推論してほしいわ
616デフォルトの名無しさん
2022/04/07(木) 18:21:01.63ID:6QFUvNfL 推論というか、型推論ね
617デフォルトの名無しさん
2022/04/07(木) 18:33:18.44ID:6J24GmAj 関数含むモジュールレベル定義の型推論はやろうと思えばできるけど
コンパイル時間への影響がでかいのと、ドキュメント的な意味で型を書いた方がわかりやすいという理由で
敢えて対応していないとどこかで読んだ気がする
とはいえ戻り値のimpl Traitは制限された形での型推論と言えるんじゃないかな
コンパイル時間への影響がでかいのと、ドキュメント的な意味で型を書いた方がわかりやすいという理由で
敢えて対応していないとどこかで読んだ気がする
とはいえ戻り値のimpl Traitは制限された形での型推論と言えるんじゃないかな
618デフォルトの名無しさん
2022/04/07(木) 18:34:30.25ID:QZwctsvV >>614
Rustでは型指定しなくて済む利点もあるしクロージャと関数の使い分けの一種じゃないかな
もちろん今回のケースはreturn値を取る別種のブロックがあれば済むけども
それをわざわざ導入しなくてもクロージャ即時呼び出しで十分
Rustでは型指定しなくて済む利点もあるしクロージャと関数の使い分けの一種じゃないかな
もちろん今回のケースはreturn値を取る別種のブロックがあれば済むけども
それをわざわざ導入しなくてもクロージャ即時呼び出しで十分
619デフォルトの名無しさん
2022/04/08(金) 04:35:42.40ID:fis9zD2L Rustのコンパイルの遅さは型推論とかじゃなく、cargoという非常に悪い仕組みのせい
620デフォルトの名無しさん
2022/04/10(日) 02:43:45.04ID:NYexxOz5 そんなことないよ
cargo build --timings いいね
cargo build --timings いいね
621デフォルトの名無しさん
2022/04/10(日) 11:44:22.72ID:UjiUu+PI Rust 1.60来てたか
622デフォルトの名無しさん
2022/04/12(火) 10:03:48.28ID:mYiJhF+M OnceCell<T> って &'static T が取れるわけじゃないんですのん?
623デフォルトの名無しさん
2022/04/12(火) 10:14:36.57ID:mYiJhF+M まちがえた
× OnceCell<T>
○ const Lazy<T>
× OnceCell<T>
○ const Lazy<T>
624デフォルトの名無しさん
2022/04/12(火) 10:20:45.37ID:9tHmQ2kh getでOption<&T>が取れる
初期化してなければNone
初期化してなければNone
625デフォルトの名無しさん
2022/04/12(火) 10:26:05.90ID:9tHmQ2kh LazyならDerefを適用させて使う
*lazyで&Tや&mut T
*lazyで&Tや&mut T
626デフォルトの名無しさん
2022/04/12(火) 10:46:54.62ID:mYiJhF+M https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=22ed821be70a494615ca8a661e98b78f
ごめんこういうこと
実際使ってるとき&'staticが取れないのが原因だと思ってそう書いちゃったけど違う原因かもしれないです
ごめんこういうこと
実際使ってるとき&'staticが取れないのが原因だと思ってそう書いちゃったけど違う原因かもしれないです
627デフォルトの名無しさん
2022/04/12(火) 11:20:51.11ID:9tHmQ2kh それはconstではなくstaticで宣言
628デフォルトの名無しさん
2022/04/12(火) 11:33:29.72ID:/UwhBms2 プログラム開始時点での有効性を保証できないから何となくだけどコンパイラの事情で無理そう
&'staticって↓みたいな使い方もできるからLazyだとBの参照先が初期化済みか分からない
static A: u32 = 0;
static B: &'static u32 = &A;
&'staticって↓みたいな使い方もできるからLazyだとBの参照先が初期化済みか分からない
static A: u32 = 0;
static B: &'static u32 = &A;
629デフォルトの名無しさん
2022/04/12(火) 11:37:37.75ID:9tHmQ2kh nightlyのstd::lazy::Lazyではなく
stableでも使えるonce_cellを使用
そのコードと同じ例がこれで動く
use once_cell::sync::Lazy;
static LAZY: Lazy<i32> = Lazy::new(|| 92);
fn main() {
let a: &'static i32 = sub();
println!("{}", *a);
}
fn sub() -> &'static i32 {
&*LAZY
}
stableでも使えるonce_cellを使用
そのコードと同じ例がこれで動く
use once_cell::sync::Lazy;
static LAZY: Lazy<i32> = Lazy::new(|| 92);
fn main() {
let a: &'static i32 = sub();
println!("{}", *a);
}
fn sub() -> &'static i32 {
&*LAZY
}
630デフォルトの名無しさん
2022/04/12(火) 11:44:54.53ID:mYiJhF+M あーなるほど
なぜか'staticでmutableなのがstatic、immutableなのがconstと勘違いしてました
constって使用の度に式展開するやつだったんですね
temporary valueなんて無いじゃんとか無限に悩んでた
ありがとうございます
なぜか'staticでmutableなのがstatic、immutableなのがconstと勘違いしてました
constって使用の度に式展開するやつだったんですね
temporary valueなんて無いじゃんとか無限に悩んでた
ありがとうございます
631デフォルトの名無しさん
2022/04/12(火) 11:47:13.23ID:9tHmQ2kh >>630
constはコンパイル時点で定まる定数
constはコンパイル時点で定まる定数
632デフォルトの名無しさん
2022/04/13(水) 09:59:43.40ID:Ee+AuAP4 こんな事も分からない触ってるだけで偉いと勘違いするゴミ言語
633デフォルトの名無しさん
2022/04/15(金) 00:23:00.39ID:jmI/h0lt634デフォルトの名無しさん
2022/04/15(金) 00:36:10.15ID:8Ev0Y6We ソフトウエアを書くにはカテゴリー論から勉強しろということかな?
635デフォルトの名無しさん
2022/04/15(金) 00:46:18.85ID:9XxTBRIR 名言もらいました
ポインタはポインタのメタファ
ポインタはポインタのメタファ
636デフォルトの名無しさん
2022/04/15(金) 00:56:52.75ID:w32fyljo >「慣れでどうにかなるもんではない」っていうのはつまり、
>わかった気になってなんとなくで書いてるやつはまだ理解してないって話でしょ。
全然違う。
型システムより先に文章を理解する訓練をした方がいいぞ。
>わかった気になってなんとなくで書いてるやつはまだ理解してないって話でしょ。
全然違う。
型システムより先に文章を理解する訓練をした方がいいぞ。
637デフォルトの名無しさん
2022/04/15(金) 01:20:52.56ID:+d47tguH638デフォルトの名無しさん
2022/04/15(金) 08:25:31.44ID:xhqbcuaF >>637
さすがにそれを「普通の人」というのは無謀。
さすがにそれを「普通の人」というのは無謀。
639デフォルトの名無しさん
2022/04/15(金) 08:41:02.84ID:WzhbtFPJ 100点オジサンや複製オジサンみたいな自分は理解してるつもりの勘違いさんが一番迷惑
640デフォルトの名無しさん
2022/04/15(金) 08:59:01.96ID:uOSWEI+/ >>638
普通のプログラマーなら他の言語でクロージャ(ラムダ等)くらいはさすがに使ったことあるから高階は大丈夫なはず
ジェネリクスもスクリプト言語などの動的型付け言語なら計らずともそのままジェネリックな関数となってる
そこでRustでのみ必要となる概念はそのジェネリックな関数内を安全な操作とするためのトレイト境界の指定
これはコンパイラがエラーとして教えてくれるため指定を忘れることがない
だから普通のプログラマーなら大丈夫じゃないかな
普通のプログラマーなら他の言語でクロージャ(ラムダ等)くらいはさすがに使ったことあるから高階は大丈夫なはず
ジェネリクスもスクリプト言語などの動的型付け言語なら計らずともそのままジェネリックな関数となってる
そこでRustでのみ必要となる概念はそのジェネリックな関数内を安全な操作とするためのトレイト境界の指定
これはコンパイラがエラーとして教えてくれるため指定を忘れることがない
だから普通のプログラマーなら大丈夫じゃないかな
641デフォルトの名無しさん
2022/04/15(金) 10:17:08.40ID:xMTiu+TR 相変わらず複製おじさんは不勉強でキツイな
「普通の人」は他の言語でジェネリック使ったことあるからこんな恥ずかしい長文を書かない
「普通の人」は他の言語でジェネリック使ったことあるからこんな恥ずかしい長文を書かない
642デフォルトの名無しさん
2022/04/15(金) 10:53:34.01ID:aXBzZfpz そうでなくRustではtrait境界が足りなければコンパイルエラーで指摘されるからスクリプト言語から来た人でも困らないって話やろ
643デフォルトの名無しさん
2022/04/15(金) 11:18:53.45ID:/A+hDicd そんなことよりこのエラーの意味を教えてくれ
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=21cdaa3e90ffdd6a5ef2e06302afe03b
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=21cdaa3e90ffdd6a5ef2e06302afe03b
644デフォルトの名無しさん
2022/04/15(金) 11:41:06.84ID:ZUiiq5D1645デフォルトの名無しさん
2022/04/15(金) 12:09:57.32ID:Y8j5AoVD おじさん使いの人はいつもそうだよな
646デフォルトの名無しさん
2022/04/15(金) 12:26:07.26ID:hAkRYyug >>640
「クロージャ(ラムダ等)くらいはさすがに使ったことある」からといって「論理とメタ的な考え……ができる」ではないことは論理的に明らか。
全然論理的な考えができていない>640自身が反証になっているね。
「クロージャ(ラムダ等)くらいはさすがに使ったことある」からといって「論理とメタ的な考え……ができる」ではないことは論理的に明らか。
全然論理的な考えができていない>640自身が反証になっているね。
647デフォルトの名無しさん
2022/04/15(金) 12:58:35.38ID:b6lK2Xo1 >>643
lifetime mismatchのエラーが分かりにくければ、lifetimeを省略せずに明記して確認すればいい
lifetime mismatchのエラーが分かりにくければ、lifetimeを省略せずに明記して確認すればいい
648デフォルトの名無しさん
2022/04/15(金) 13:07:01.81ID:FU35awjY あと#![feature(nll)]でビルドしても分かるはず
649デフォルトの名無しさん
2022/04/15(金) 13:08:53.72ID:OaJu93JV >>646
むしろ論理とメタわからんプログラマーは言語関係なく向いてないっす
むしろ論理とメタわからんプログラマーは言語関係なく向いてないっす
650デフォルトの名無しさん
2022/04/15(金) 13:30:54.07ID:uTkCAN7R 理解の程度を0か1で考える人は底辺プログラマーに向いてる
651デフォルトの名無しさん
2022/04/15(金) 14:19:47.21ID:Xm9+ELTI 所有権でよくわからないって言えばさあ
fn asdf() -> &str{
let s = "jkl";
s
}
みたいにした時に、関数を抜ける際にstrのライフタイムが尽きちゃう訳じゃない
でも逆になぜ&strしかないのに、どうして関数を抜けるところまでstrのライフタイムが持つのか?そこら辺がよくわからねえな
&strを通じてstrを所有できているのであれば、&strをリターンできても良いような気もするのに・・・・どうなってんの?
fn asdf() -> &str{
let s = "jkl";
s
}
みたいにした時に、関数を抜ける際にstrのライフタイムが尽きちゃう訳じゃない
でも逆になぜ&strしかないのに、どうして関数を抜けるところまでstrのライフタイムが持つのか?そこら辺がよくわからねえな
&strを通じてstrを所有できているのであれば、&strをリターンできても良いような気もするのに・・・・どうなってんの?
652デフォルトの名無しさん
2022/04/15(金) 15:21:50.13ID:k/yGxJzN >>651
fn asdf() -> &str
は
fn asdf<'a>() ->&'a str
のようにlifetimeを省略した記法なんだけど、
この 'a は引数にも現れないし何の寿命に対応するか分からないからエラーになっちゃう
今回の文字列リテラルみたいにプログラム開始から終了まで存在するデータへの参照なら、
プログラム開始から終了までを意味する 'static を使うことはできる
fn asdf() -> &'static str
また以下のように引数に参照が登場する場合は、
戻り値の寿命は暗黙的に引数と同じだと見なされる
fn asdf(a: &str) -> &str
は
fn asdf<'a>(a: &'a str) -> &'a str
となるということ
この辺の仕組みは lifetime elision でググると情報出てくるよ
fn asdf() -> &str
は
fn asdf<'a>() ->&'a str
のようにlifetimeを省略した記法なんだけど、
この 'a は引数にも現れないし何の寿命に対応するか分からないからエラーになっちゃう
今回の文字列リテラルみたいにプログラム開始から終了まで存在するデータへの参照なら、
プログラム開始から終了までを意味する 'static を使うことはできる
fn asdf() -> &'static str
また以下のように引数に参照が登場する場合は、
戻り値の寿命は暗黙的に引数と同じだと見なされる
fn asdf(a: &str) -> &str
は
fn asdf<'a>(a: &'a str) -> &'a str
となるということ
この辺の仕組みは lifetime elision でググると情報出てくるよ
653デフォルトの名無しさん
2022/04/15(金) 15:35:47.27ID:/A+hDicd >>647
>>648
両方やってみて結局こうなったがまだよく分からん
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=aafabd8057a50f537f9ff410c03461d2
yが借用中にもかかわらずdropされたというふうに読めるけど、f(&mut y)が終わった時点で借用も終わってるから問題無いのでは?
でも試しにこの後yをどうこうするコード付け足してみると、どうも借用しっぱなしになってるっぽいエラーばっかり出るのよな
>>648
両方やってみて結局こうなったがまだよく分からん
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=aafabd8057a50f537f9ff410c03461d2
yが借用中にもかかわらずdropされたというふうに読めるけど、f(&mut y)が終わった時点で借用も終わってるから問題無いのでは?
でも試しにこの後yをどうこうするコード付け足してみると、どうも借用しっぱなしになってるっぽいエラーばっかり出るのよな
654デフォルトの名無しさん
2022/04/15(金) 16:44:22.79ID:tw5ISWTc655デフォルトの名無しさん
2022/04/15(金) 17:24:32.32ID:k/yGxJzN656デフォルトの名無しさん
2022/04/15(金) 17:51:47.56ID:VZ7u/ZvT >>648
これさらにわかりやすくなるね
これさらにわかりやすくなるね
657デフォルトの名無しさん
2022/04/15(金) 19:50:10.79ID:rQzdCva+ ありがとう!
なんかちょっとズレたエラーメッセージだなと思っても、省略・推論されているなんて夢にも思わなかったから意味がわんなかったぜ!
なんかちょっとズレたエラーメッセージだなと思っても、省略・推論されているなんて夢にも思わなかったから意味がわんなかったぜ!
658デフォルトの名無しさん
2022/04/16(土) 15:01:46.93ID:Tmn9GDW2 Rustって参照をベクターに持てる?
659デフォルトの名無しさん
2022/04/16(土) 15:58:22.55ID:hx1ZC8lU >>658
もてるよ
https://ideone.com/ZMCl2R
fn main() {
let a = 1;
let b = 2;
let v = vec![&a, &b, &a, &b];
println!("{:?}", &v);
}
もてるよ
https://ideone.com/ZMCl2R
fn main() {
let a = 1;
let b = 2;
let v = vec![&a, &b, &a, &b];
println!("{:?}", &v);
}
660デフォルトの名無しさん
2022/04/16(土) 17:14:58.83ID:Tmn9GDW2 >>659
サンクス
サンクス
661デフォルトの名無しさん
2022/04/20(水) 18:37:23.24ID:3eLEi52G Rust 入門者です。
全く実用的な意味はなく練習として符号無し整数を桁ごとに返すイテレータというものを考えていたのですが
同じ制約を重複して書くことになってしまい不格好な気がします。
https://ideone.com/qOmnhW
ベテランが華麗に書いたらどんな風になりますでしょうか。
それとも Rust ではこれで良いものなのでしょうか。
全く実用的な意味はなく練習として符号無し整数を桁ごとに返すイテレータというものを考えていたのですが
同じ制約を重複して書くことになってしまい不格好な気がします。
https://ideone.com/qOmnhW
ベテランが華麗に書いたらどんな風になりますでしょうか。
それとも Rust ではこれで良いものなのでしょうか。
662デフォルトの名無しさん
2022/04/20(水) 19:13:19.89ID:uLqNeO4/ >>661
traitの方の制約はいらないよ
traitの方の制約はいらないよ
663デフォルトの名無しさん
2022/04/20(水) 22:38:14.51ID:3eLEi52G >>662
ありがとうございます。
たしかにこのコードではトレイト Digits にスーパートレイトを付ける必要はないですね。
想定を後出しにして誠に申し訳ないのですが、これはライブラリ (クレート) としてまとめようとしているつもりでした。
ここに書かれていない未知の型にトレイト Digits を実装することがあり得るという意味です。
問題になるのは、 Digits のスーパートレイトを消してしまうとどんな型でも Digits の実装自体は出来てしまうということです。
// ↓ Digits にスーパートレイトを付けなければこう書くこと自体は出来てしまう。 この段階でエラーになって欲しい。
struct Foo {}
impl Digits for Foo {}
そしてメソッド digits を呼出すところでエラーになります。
let bar = Foo {};
for x in bar.digits() { // ← ここでエラーになる
println!("{}", x);
}
逆に言えば digits を呼出さなければエラーになりません。
どうせ使えないことがわかっているならトレイトの impl の段階でエラーであって然るべきだという判断が
重複する制約を書いた意図です。
メソッドがイテレータを返すなんていうのはよくあることだと思うので、
いちいち重複したことを書かかなくて済むような何かがあるんじゃないか……という想像から質問した次第です。
ありがとうございます。
たしかにこのコードではトレイト Digits にスーパートレイトを付ける必要はないですね。
想定を後出しにして誠に申し訳ないのですが、これはライブラリ (クレート) としてまとめようとしているつもりでした。
ここに書かれていない未知の型にトレイト Digits を実装することがあり得るという意味です。
問題になるのは、 Digits のスーパートレイトを消してしまうとどんな型でも Digits の実装自体は出来てしまうということです。
// ↓ Digits にスーパートレイトを付けなければこう書くこと自体は出来てしまう。 この段階でエラーになって欲しい。
struct Foo {}
impl Digits for Foo {}
そしてメソッド digits を呼出すところでエラーになります。
let bar = Foo {};
for x in bar.digits() { // ← ここでエラーになる
println!("{}", x);
}
逆に言えば digits を呼出さなければエラーになりません。
どうせ使えないことがわかっているならトレイトの impl の段階でエラーであって然るべきだという判断が
重複する制約を書いた意図です。
メソッドがイテレータを返すなんていうのはよくあることだと思うので、
いちいち重複したことを書かかなくて済むような何かがあるんじゃないか……という想像から質問した次第です。
664デフォルトの名無しさん
2022/04/20(水) 23:00:49.13ID:uLqNeO4/ >>663
そういう前提ならばこんな感じで impl の方の制約を T: Digits に変えるのはどうじゃろ
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6bd0ab54e4cbd88ca2a0502f9e74315d
あと T::Error: std::fmt::Debug についてはどの trait の associated type に対する制約か分かり辛いから
<T as std::convert::TryInto<u8>>::Error: std::fmt::Debug,
としても良いかもね
そういう前提ならばこんな感じで impl の方の制約を T: Digits に変えるのはどうじゃろ
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6bd0ab54e4cbd88ca2a0502f9e74315d
あと T::Error: std::fmt::Debug についてはどの trait の associated type に対する制約か分かり辛いから
<T as std::convert::TryInto<u8>>::Error: std::fmt::Debug,
としても良いかもね
665デフォルトの名無しさん
2022/04/21(木) 00:02:58.32ID:9+GFB0OX666デフォルトの名無しさん
2022/04/21(木) 13:57:26.69ID:Ast3pmta 数値にメソッドを生やすメリットが思いつかないからこれだけでいいんじゃない?
fn digits<T>(n: T) -> impl Iterator<Item=T>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>
{
itertools::unfold(n, |n| (*n != T::from(0)).then(|| {
let rem = n.clone() % T::from(10);
*n /= T::from(10);
rem
}))
}
fn main() {
let foo: i64 = 9165731750932755204;
for x in digits(foo) {
println!("{x}");
}
}
fn digits<T>(n: T) -> impl Iterator<Item=T>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>
{
itertools::unfold(n, |n| (*n != T::from(0)).then(|| {
let rem = n.clone() % T::from(10);
*n /= T::from(10);
rem
}))
}
fn main() {
let foo: i64 = 9165731750932755204;
for x in digits(foo) {
println!("{x}");
}
}
667デフォルトの名無しさん
2022/04/21(木) 14:14:33.93ID:Q5xBjMYc 実用上は関数で十分だろうけど、Rustって整数のプリミティブ型にもたくさんメソッドあるし、
メソッドを生やすのが流儀なのかな、って俺も思ってたけどどうなんやろ?
メソッドを生やすのが流儀なのかな、って俺も思ってたけどどうなんやろ?
669デフォルトの名無しさん
2022/04/21(木) 22:20:02.87ID:NWAfliAT >>666の関数をメソッド化しようとしたら
traitやimplの中では関数はimpl Iteratorを返せないと怒られた
この制限は将来緩和される可能性ある?
implでなく返す型を具体化したらコンパイル通って動いた
traitとimplでwhereのところが冗長な気がするけど両方とも外せない?
trait Digits<T> {
fn digits(self) -> itertools::Unfold<T, fn(&mut T) -> Option<T>>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>;
}
impl<T> Digits<T> for T {
fn digits(self: T) -> itertools::Unfold<T, fn(&mut T) -> Option<T>>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>,
{
itertools::unfold(self, |n| (*n != T::from(0)).then(|| {
let rem = n.clone() % T::from(10);
*n /= T::from(10);
rem
}))
}
}
fn main() {
let foo: i64 = 9165731750932755204;
for x in foo.digits() {
println!("{x}");
}
}
traitやimplの中では関数はimpl Iteratorを返せないと怒られた
この制限は将来緩和される可能性ある?
implでなく返す型を具体化したらコンパイル通って動いた
traitとimplでwhereのところが冗長な気がするけど両方とも外せない?
trait Digits<T> {
fn digits(self) -> itertools::Unfold<T, fn(&mut T) -> Option<T>>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>;
}
impl<T> Digits<T> for T {
fn digits(self: T) -> itertools::Unfold<T, fn(&mut T) -> Option<T>>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>,
{
itertools::unfold(self, |n| (*n != T::from(0)).then(|| {
let rem = n.clone() % T::from(10);
*n /= T::from(10);
rem
}))
}
}
fn main() {
let foo: i64 = 9165731750932755204;
for x in foo.digits() {
println!("{x}");
}
}
670デフォルトの名無しさん
2022/04/22(金) 09:19:03.80ID:oJU3aoBf rfc2071かな
671デフォルトの名無しさん
2022/04/22(金) 09:42:40.77ID:sg+qNIV4 >>670
こんな記述もできるようになるわけね
let displayable: impl Display = "Hello, world!";
const MY_CLOSURE: impl Fn(i32) -> i32 = |x| x + 1;
let x: impl Iterator<Item = i32> = (0..100).map(|x| x * 3).filter(|x| x % 5);
こんな記述もできるようになるわけね
let displayable: impl Display = "Hello, world!";
const MY_CLOSURE: impl Fn(i32) -> i32 = |x| x + 1;
let x: impl Iterator<Item = i32> = (0..100).map(|x| x * 3).filter(|x| x % 5);
672デフォルトの名無しさん
2022/04/22(金) 11:24:39.82ID:QUxpZq2Z673デフォルトの名無しさん
2022/04/22(金) 11:28:58.18ID:xFM+XidE >>672
具体的にはどんなコードになるのですか?
具体的にはどんなコードになるのですか?
674デフォルトの名無しさん
2022/04/22(金) 11:29:43.00ID:QUxpZq2Z >>669
>>672 の意図はこんな感じ。返り値も associated type にして実装に委ねられるようにした。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1dfdb310cd07023a69acca6cbba434ed
>>672 の意図はこんな感じ。返り値も associated type にして実装に委ねられるようにした。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1dfdb310cd07023a69acca6cbba434ed
675デフォルトの名無しさん
2022/04/22(金) 12:09:33.52ID:L/Q81szU >>674
where制約宣言の場所をメソッドfnからimplへ移動させることで結果的にtrait側で制約する必要がなくなるわけか
where制約宣言の場所をメソッドfnからimplへ移動させることで結果的にtrait側で制約する必要がなくなるわけか
676661
2022/04/22(金) 13:12:07.76ID:rYail8LQ >>674
元々の想定では符号付きの場合を型の制約で排除したいと考えていました。
トレイトが実装されているかどうかだけでは必要な性質を満たしているかどうか判定しきれないと考えて
個別に実装する必要があるという判断をした次第です。
個々に人が判断するのではなく制約で包括的に判定するとしたら std::ops::Neg を実装して「いない」という条件を付ける
必要が出てくるかと思いますが、今の Rust だとそういう制約は付けられないですよね?
元々の想定では符号付きの場合を型の制約で排除したいと考えていました。
トレイトが実装されているかどうかだけでは必要な性質を満たしているかどうか判定しきれないと考えて
個別に実装する必要があるという判断をした次第です。
個々に人が判断するのではなく制約で包括的に判定するとしたら std::ops::Neg を実装して「いない」という条件を付ける
必要が出てくるかと思いますが、今の Rust だとそういう制約は付けられないですよね?
677デフォルトの名無しさん
2022/04/22(金) 14:11:21.60ID:RekYcGSo678デフォルトの名無しさん
2022/04/24(日) 14:55:18.07ID:SDl1bpLd >>675
trait宣言でtrait境界制約しないメリットは他にもある
例えば文字列(例 "57261")に対するdigits()をimplできるようになってこの場合は別のtrait境界をimpl側で書くことになる
ただし別問題として現状ではまだ安定化していない2つの機能サポート待ち
1つ目はimpl Traitのspecializationでfor Tが既にあるところへfor Stringやfor &strできるようにするため
もう1つはGATs (general associated types)でイテレータで参照返しできるようにするため
trait宣言でtrait境界制約しないメリットは他にもある
例えば文字列(例 "57261")に対するdigits()をimplできるようになってこの場合は別のtrait境界をimpl側で書くことになる
ただし別問題として現状ではまだ安定化していない2つの機能サポート待ち
1つ目はimpl Traitのspecializationでfor Tが既にあるところへfor Stringやfor &strできるようにするため
もう1つはGATs (general associated types)でイテレータで参照返しできるようにするため
679デフォルトの名無しさん
2022/04/25(月) 18:30:29.96ID:5VI7zZaU String の配列でパターンマッチしたいと考えていますが、
こういう書き方をすると String と &str を比較しているとして型が合いません。
fn main() {
let foo = [String::from("bar")];
let baz = match foo { ["bar"] => 1, _ => 2 };
}
かといって書けるパターンは制限があるので↓こう書くことも出来ません。
fn main() {
let foo = [String::from("bar")];
let baz = match foo { [String::from("bar")] => 1, _ => 2};
}
ガードを付けるかスライスの配列を作るかくらいしか方法はないですかね?
fn main() {
let foo = [String::from("bar")];
let baz = match foo { [ref x] if x =="bar" => 1, _ => 2 };
}
fn main() {
let foo = [String::from("bar")];
let bar = &foo.iter().map(|ref str|&str[..]).collect::<Vec<_>>()[..];
let baz = match bar { ["bar"] => 1, _ => 2 };
}
こういう書き方をすると String と &str を比較しているとして型が合いません。
fn main() {
let foo = [String::from("bar")];
let baz = match foo { ["bar"] => 1, _ => 2 };
}
かといって書けるパターンは制限があるので↓こう書くことも出来ません。
fn main() {
let foo = [String::from("bar")];
let baz = match foo { [String::from("bar")] => 1, _ => 2};
}
ガードを付けるかスライスの配列を作るかくらいしか方法はないですかね?
fn main() {
let foo = [String::from("bar")];
let baz = match foo { [ref x] if x =="bar" => 1, _ => 2 };
}
fn main() {
let foo = [String::from("bar")];
let bar = &foo.iter().map(|ref str|&str[..]).collect::<Vec<_>>()[..];
let baz = match bar { ["bar"] => 1, _ => 2 };
}
680デフォルトの名無しさん
2022/04/25(月) 19:55:08.99ID:6A0Kp8FF >>679
配列は長さ固定
長さが異なれば別の型となる
マッチングは全て同じ型でなければならない
つまり長さ1の配列パターンがあるならば全て長さ1の配列
つまり配列としてマッチングする必要がない
実際には長い配列で先頭だけマッチングしているとしてもfoo[0].as_str()でよい
おそらく例として簡略化して書いたのだろうがもう少し具体化した方がアドバイスを受けやすい
配列は長さ固定
長さが異なれば別の型となる
マッチングは全て同じ型でなければならない
つまり長さ1の配列パターンがあるならば全て長さ1の配列
つまり配列としてマッチングする必要がない
実際には長い配列で先頭だけマッチングしているとしてもfoo[0].as_str()でよい
おそらく例として簡略化して書いたのだろうがもう少し具体化した方がアドバイスを受けやすい
681デフォルトの名無しさん
2022/04/25(月) 23:28:44.10ID:QcJ2t2WS 配列を使わずにスライスを使えば可変長マッチングができる
682デフォルトの名無しさん
2022/04/26(火) 02:22:33.26ID:9/mVSM+b 問題はそこじゃなくて &[String] をパターンマッチする方法がないってことだよね
683デフォルトの名無しさん
2022/04/26(火) 02:43:40.86ID:uT+rLtYK Stringのままだと、文字列のマッチはガードでやるしかなそうだし、
その場合なら &str にしてからマッチしたほうが良さそうだね
その場合なら &str にしてからマッチしたほうが良さそうだね
684デフォルトの名無しさん
2022/04/26(火) 13:29:24.27ID:v9kFaZ9R 変換するならばヒープ使わずに配列mapかな
match foo.map(String::as_str) はちょっと惜しかった
match foo.map(String::as_str) はちょっと惜しかった
685デフォルトの名無しさん
2022/04/26(火) 14:28:08.93ID:9/mVSM+b 配列mapだと元のStringがdropされるから&str作れないのでは
686デフォルトの名無しさん
2022/04/26(火) 15:51:55.40ID:y3S6RL/9 配列mapは別の配列となる
元は消えないのでdropはされない
元は消えないのでdropはされない
687デフォルトの名無しさん
2022/04/26(火) 16:05:15.07ID:MauoWn9e 別の配列になるけど
mapがなぜかselfを要求する
つまりStringの配列に対して何もできない
Stringの長さの配列すら生成不可能
Copy実装型の配列に対してしかmapを使えないのではないか
mapがなぜかselfを要求する
つまりStringの配列に対して何もできない
Stringの長さの配列すら生成不可能
Copy実装型の配列に対してしかmapを使えないのではないか
689デフォルトの名無しさん
2022/04/26(火) 16:57:38.42ID:o3+/PYQ+ >>688
配列mapはイテレータとは無関係
配列mapはイテレータとは無関係
691デフォルトの名無しさん
2022/04/26(火) 17:08:44.26ID:9/mVSM+b >>687
長さの配列は元のStringへの参照を保持するわけではないから生成可能
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1389138f28b6679332ad660d8920ea5e
元のStringがconsumeされるのでStringへの参照を持つようなデータへの変換はできない
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f358e19998b508fe1955ea5274a7daf5
元の配列がdropされて良いならCopyな型に対してしか使えないということはないよ
例えば構造体の一部フィールドだけ変更するみたいな用途にも使える
長さの配列は元のStringへの参照を保持するわけではないから生成可能
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1389138f28b6679332ad660d8920ea5e
元のStringがconsumeされるのでStringへの参照を持つようなデータへの変換はできない
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f358e19998b508fe1955ea5274a7daf5
元の配列がdropされて良いならCopyな型に対してしか使えないということはないよ
例えば構造体の一部フィールドだけ変更するみたいな用途にも使える
692デフォルトの名無しさん
2022/04/26(火) 17:13:18.82ID:6GFvJMAy each_ref()を使えばできるよ
693デフォルトの名無しさん
2022/04/26(火) 17:20:49.70ID:6GFvJMAy &strの配列に変換してから比較すると変換時と比較時とで2周するのと
比較対象がconst相当じゃないとだめなのでguardのほうがベターなケースが多いと思う
比較対象がconst相当じゃないとだめなのでguardのほうがベターなケースが多いと思う
694デフォルトの名無しさん
2022/04/26(火) 17:38:44.61ID:+plNly3p 配列mapは新たな配列を作る
つまり配列map自体が元の配列をdropするわけではない
Copyを実装していない型の時はmoveとなるため結果として元の配列がdropされる
Copyを実装している型の時はmoveが起きないため元の配列もそのまま使える
// Copyを実装していない型の場合
#[derive(Debug)]
struct XM(i32);
let a1 = [XM(1), XM(2), XM(3)];
let a2 = a1.map(|XM(n)| n);
println!("{a2:?}");
// println!("{a1:?}"); // エラーとなる
// Copyを実装している型の場合
#[derive(Debug,Clone,Copy)]
struct XC(i32);
let a1 = [XC(1), XC(2), XC(3)];
let a2 = a1.map(|XC(n)| n);
println!("{a2:?}");
println!("{a1:?}"); // エラーとならず元の配列も残っている
つまり配列map自体が元の配列をdropするわけではない
Copyを実装していない型の時はmoveとなるため結果として元の配列がdropされる
Copyを実装している型の時はmoveが起きないため元の配列もそのまま使える
// Copyを実装していない型の場合
#[derive(Debug)]
struct XM(i32);
let a1 = [XM(1), XM(2), XM(3)];
let a2 = a1.map(|XM(n)| n);
println!("{a2:?}");
// println!("{a1:?}"); // エラーとなる
// Copyを実装している型の場合
#[derive(Debug,Clone,Copy)]
struct XC(i32);
let a1 = [XC(1), XC(2), XC(3)];
let a2 = a1.map(|XC(n)| n);
println!("{a2:?}");
println!("{a1:?}"); // エラーとならず元の配列も残っている
695デフォルトの名無しさん
2022/04/26(火) 18:27:08.74ID:rgPp8Pfc 意味不明な解説だな
「array::mapはselfを要求する」の一言で済む話だろ
「array::mapはselfを要求する」の一言で済む話だろ
696デフォルトの名無しさん
2022/04/26(火) 18:33:28.01ID:WcuXDkX5 配列mapは
Stringの配列を&strの配列に変換できないけど
&Stringの配列を&strの配列に変換できるよ
つまり
Stringの配列を&Stringの配列に変換できればよくてそれがeach_ref()
Stringの配列を&strの配列に変換できないけど
&Stringの配列を&strの配列に変換できるよ
つまり
Stringの配列を&Stringの配列に変換できればよくてそれがeach_ref()
697デフォルトの名無しさん
2022/04/26(火) 19:46:56.99ID:/uwAuiMA each_ref()はまだstableじゃないので
Stringを&strにしておく方法でヒープ(Vec)を使わないならこうかな
let x: [String; 3] = ["foo".into(), "bar".into(), "baz".into()];
let y: ArrayVec<&str, 3> = x.iter().map(|s| &**s).collect();
let z = match &y[..] { ["foo", ..] => 1, _ => 2 };
Stringを&strにしておく方法でヒープ(Vec)を使わないならこうかな
let x: [String; 3] = ["foo".into(), "bar".into(), "baz".into()];
let y: ArrayVec<&str, 3> = x.iter().map(|s| &**s).collect();
let z = match &y[..] { ["foo", ..] => 1, _ => 2 };
698デフォルトの名無しさん
2022/04/26(火) 21:05:30.47ID:FU096Fs4 こういう何がしたいのか分かりにくいだけのコードは勘弁して欲しいな
699デフォルトの名無しさん
2022/04/26(火) 21:13:08.58ID:YFyFIjJ4 iter→map→collectだけのコードが分かりにくい、って初心者でも言わないだろw
3行目の数値1と2は謎だが>>679の質問者のコードそのままだな
3行目の数値1と2は謎だが>>679の質問者のコードそのままだな
700デフォルトの名無しさん
2022/04/26(火) 21:47:45.37ID:ttl254Ty mapの中身は(|s| s.as_str())にしたいな
初心者だけど&**sはちょっと分かりにくい
初心者だけど&**sはちょっと分かりにくい
701デフォルトの名無しさん
2022/04/26(火) 21:55:49.66ID:zrm7en4p そういう視点ならば
match &y[..] のところも
match y.as_slice() にする?
match &y[..] のところも
match y.as_slice() にする?
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 首相官邸前で「戦争あおるな」 台湾有事巡る答弁に抗議 [蚤の市★]
- 高市首相告白「『なめられない服』を選ぶことに数時間を費やしました」「外交交渉でマウント取れる服、買わなくてはいかんかもなぁ」 [ぐれ★]
- 【高市リスク】立民・小西洋之参院議員「高市総理がとんでもない安全保障オンチで外交オンチ」 [ぐれ★]
- 『DOWNTOWN+』会員数50万人突破で見えてきた 松本人志の“月収4ケタ万円”驚愕収入 [阿弥陀ヶ峰★]
- 【赤坂ライブハウス刺傷】逃走していた自衛官の男(43)を殺人未遂の疑いで逮捕 警視庁 被害女性とは知人関係 [Ailuropoda melanoleuca★]
- 【音楽】クラフトワークの来日公演決定 [湛然★]
- 夜勤終わり風呂なう
- 桃香さん!!
- 【悲報】東京都民さん、20過ぎてるのに自転車に乗っててて大炎上wwwwwwwwwwww女「いい歳した男で自転車に乗るのは知的障がい者だけだよ? [483447288]
- 【悲報】ミスター東大さん、高度な『ずらし』を披露するも愚民には理解されず大炎上wwwwwwwwwwww [455031798]
- 【悲報】細田守最新作、超絶爆死しそう
- 【悲報】「全国の独身男性2000万人に年間120万円の独身税をかけるだけで農家を守って米の値段を半分にできるんだよ」8万高市 [257926174]
