公式
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の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 part12
https://mevius.5ch.net/test/read.cgi/tech/1629813327/
Rust part13
■ このスレッドは過去ログ倉庫に格納されています
2021/11/07(日) 10:04:59.35ID:pJhT3MIE
2021/11/07(日) 14:35:43.57ID:GwJCd0Qm
>>7
間接的にアクセスしうるとかいうのはもちろんあるけど、
あくまでもプログラマが読み書きする上での意図として明示するという意味ね。
実際にもう (直接には) 使えないんだから使えないという意味だよ。
間接的にアクセスしうるとかいうのはもちろんあるけど、
あくまでもプログラマが読み書きする上での意図として明示するという意味ね。
実際にもう (直接には) 使えないんだから使えないという意味だよ。
9デフォルトの名無しさん
2021/11/07(日) 14:45:10.83ID:K5DEbKWG ん?まあありうるだろうけど、そんな意図を持ってシャドーイングをするコードは捨てろよ?明示じゃねーわ
2021/11/07(日) 15:07:42.51ID:GwJCd0Qm
そうか。
11デフォルトの名無しさん
2021/11/07(日) 15:10:45.19ID:XJB+ymj6 >>996
C/C++だとスコープ中で外のスコープの宣言と被ってたら警告出るよね
C/C++だとスコープ中で外のスコープの宣言と被ってたら警告出るよね
2021/11/07(日) 15:27:52.97ID:BjoZRpKT
13デフォルトの名無しさん
2021/11/07(日) 16:09:12.89ID:XJB+ymj6 おま環
2021/11/07(日) 16:58:36.83ID:NoqiBvXu
intellijでも、シャドーイングがあったときは警告出てなかったっけ?
15デフォルトの名無しさん
2021/11/07(日) 17:10:25.95ID:qLFsTeDp 変数名にシャドーイングって含めとけばいいのでは
16デフォルトの名無しさん
2021/11/07(日) 17:23:30.13ID:BGBI+61D そんなことよりもだ!Rustに限らないけど
これって誰も食いつかないんだけど、1と2どっちが良いか、そろそろ決着つけてくれ
let upper = 1000;
// 1、これと
let mut acc = 0;
for n in 0.. {
let n_squared = n * n;
if n_squared >= upper {
break;
} else if n_squared % 2 == 1 {
acc += n_squared;
}
}
// 2、これ
let acc1: u32 = (0..).map(|n| n * n)
.take_while(|&n_squared| n_squared < upper)
.filter(|&n_squared| is_odd(n_squared))
.fold(0, |acc, n_squared| acc + n_squared);
これって誰も食いつかないんだけど、1と2どっちが良いか、そろそろ決着つけてくれ
let upper = 1000;
// 1、これと
let mut acc = 0;
for n in 0.. {
let n_squared = n * n;
if n_squared >= upper {
break;
} else if n_squared % 2 == 1 {
acc += n_squared;
}
}
// 2、これ
let acc1: u32 = (0..).map(|n| n * n)
.take_while(|&n_squared| n_squared < upper)
.filter(|&n_squared| is_odd(n_squared))
.fold(0, |acc, n_squared| acc + n_squared);
2021/11/07(日) 17:27:45.44ID:Vt90/0HU
foldじゃなくてsumのほうが良いのでは
18デフォルトの名無しさん
2021/11/07(日) 17:29:32.83ID:TOVMzjUd let acc1: u32 = (0..).map(|n| n * n)
.take_while(|&n_squared| n_squared < upper)
.filter(is_odd)
.sum()
.take_while(|&n_squared| n_squared < upper)
.filter(is_odd)
.sum()
19991
2021/11/07(日) 17:45:31.24ID:tLg/y1Lc >>5
不意のミスでも結構コンパイルで引っかかってくれるようで安心しました。Rustさんよく考えられてますね。知りたかったことが書いてありました。ご丁寧にありがとうございます
不意のミスでも結構コンパイルで引っかかってくれるようで安心しました。Rustさんよく考えられてますね。知りたかったことが書いてありました。ご丁寧にありがとうございます
2021/11/07(日) 18:44:40.25ID:jMCdC4Py
shadowing嫌いな人はdeny(clippy::shadow_same)などすればよい
21デフォルトの名無しさん
2021/11/07(日) 18:52:44.84ID:UxYGnxuj >>16
High orders functionはソースが配列かイテレーターか、いずれかで注意が必要です。配列の場合は以下の
英文のようになります。つまりそのサイズのメモリー領域が必要になるということです。またイテレータの
時でもある程度メモリーは当然使用しますが、それよりも遅延評価されるので注意が必要です。
Note on performance and stack usage
Unfortunately, usages of this method are currently not always optimized as well as they could be.
This mainly concerns large arrays, as mapping over small arrays seem to be optimized just fine.
Also note that in debug mode (i.e. without any optimizations), this method can use a lot of stack space
(a few times the size of the array or more).
Therefore, in performance-critical code, try to avoid using this method on large arrays or check
the emitted code. Also try to avoid chained maps (e.g. arr.map(...).map(...)).
個人的には深いチェーン呼び出しはあまり好きではありません。なぜなら状態をデバックしにくいからです。
パフォーマンス的な罠がありデバックしにくい事を抜けば、map,take_while,filterなどは何を行うかforに
比べ意図が明確になりますが、それは自己満足の幅が大きいとも言えます
High orders functionはソースが配列かイテレーターか、いずれかで注意が必要です。配列の場合は以下の
英文のようになります。つまりそのサイズのメモリー領域が必要になるということです。またイテレータの
時でもある程度メモリーは当然使用しますが、それよりも遅延評価されるので注意が必要です。
Note on performance and stack usage
Unfortunately, usages of this method are currently not always optimized as well as they could be.
This mainly concerns large arrays, as mapping over small arrays seem to be optimized just fine.
Also note that in debug mode (i.e. without any optimizations), this method can use a lot of stack space
(a few times the size of the array or more).
Therefore, in performance-critical code, try to avoid using this method on large arrays or check
the emitted code. Also try to avoid chained maps (e.g. arr.map(...).map(...)).
個人的には深いチェーン呼び出しはあまり好きではありません。なぜなら状態をデバックしにくいからです。
パフォーマンス的な罠がありデバックしにくい事を抜けば、map,take_while,filterなどは何を行うかforに
比べ意図が明確になりますが、それは自己満足の幅が大きいとも言えます
2021/11/07(日) 19:20:41.26ID:AmV/cRIg
23デフォルトの名無しさん
2021/11/07(日) 19:35:16.03ID:UxYGnxuj >>22
18のコードは配列ではなくイテレーターなのでそうですが、map,take_while,filterのほうが
好みの人が多いとは思いますが、私が言いたいのは何でもかんでもHigh orders functionに
して書くのはよく知らないと、リスクがあるということとブレークポイントなどを仕掛けて
経過は見れないということです。日本語が読めない人はもう少し考えましょう
18のコードは配列ではなくイテレーターなのでそうですが、map,take_while,filterのほうが
好みの人が多いとは思いますが、私が言いたいのは何でもかんでもHigh orders functionに
して書くのはよく知らないと、リスクがあるということとブレークポイントなどを仕掛けて
経過は見れないということです。日本語が読めない人はもう少し考えましょう
2021/11/07(日) 19:40:56.86ID:BxmvbDqp
メソッドチェーンなら、メソッドごとに単体テストができるし、テストを用意しとけばすぐにバグがわかるような気がするが。
25デフォルトの名無しさん
2021/11/07(日) 21:07:08.18ID:UxYGnxuj ほんと日本語読めない奴ばっかり。経過いうてるのにメソッド毎だとか、バグのことなんて言って
ないのに(特殊な例を言えば配列の場合でmap().map()などとしたメモリー使用量)を言っている
のに、そもそも個人的には言うてんのに、そんなに説得したいのか?
ないのに(特殊な例を言えば配列の場合でmap().map()などとしたメモリー使用量)を言っている
のに、そもそも個人的には言うてんのに、そんなに説得したいのか?
2021/11/07(日) 21:12:13.09ID:0IMrdMn2
翻訳は、Chrome, Edge の翻訳機能、
Google の翻訳サイトとか、DeepL とか
Google の翻訳サイトとか、DeepL とか
2021/11/07(日) 21:12:13.85ID:t/1xwUA+
経過も見れるよ
28デフォルトの名無しさん
2021/11/07(日) 21:20:10.03ID:UxYGnxuj 言語は素晴らしいのにやってる奴が意識高い系のウンコ野郎ばっかり
29デフォルトの名無しさん
2021/11/07(日) 21:27:42.49ID:aMDc0Kvs まあコミュニティに馴染めるかどうかも本人の適性によるところがあるしな
2021/11/07(日) 22:21:32.27ID:BjoZRpKT
>>25
前回から新たに導入されたfn map([T; N], FnMut(T) -> U) -> [U; N]を何度も使えば配列地獄になるけど
昔からあるIterator::map()を使えば小さな struct Mapの分しか容量を喰わないよ
前者: assert_eq!(10, [1, 2, 3, 4, 5].map(|n| n - 3).map(|n| n * n).into_iter().sum());
後者: assert_eq!(10, [1, 2, 3, 4, 5].into_iter().map(|n| n - 3).map(|n| n * n).sum());
したがってこの件でメソッドチェーンを批判するのはおかしい
そして元々の>>16課題forを使うか>>18のメソッドチェーンを使うかの話に配列は一切関係ない
前回から新たに導入されたfn map([T; N], FnMut(T) -> U) -> [U; N]を何度も使えば配列地獄になるけど
昔からあるIterator::map()を使えば小さな struct Mapの分しか容量を喰わないよ
前者: assert_eq!(10, [1, 2, 3, 4, 5].map(|n| n - 3).map(|n| n * n).into_iter().sum());
後者: assert_eq!(10, [1, 2, 3, 4, 5].into_iter().map(|n| n - 3).map(|n| n * n).sum());
したがってこの件でメソッドチェーンを批判するのはおかしい
そして元々の>>16課題forを使うか>>18のメソッドチェーンを使うかの話に配列は一切関係ない
2021/11/07(日) 22:27:15.28ID:jMCdC4Py
配列とスライスとベクタが別物なのこういう場所で会話するときに地味に混乱しがち
2021/11/07(日) 22:28:05.16ID:jMCdC4Py
Stringとstrって日本語でどう呼び分けるんですか?
33デフォルトの名無しさん
2021/11/08(月) 07:17:46.35ID:59xs5iEI inspectで経過見れるじゃん
34デフォルトの名無しさん
2021/11/08(月) 07:29:23.24ID:n6XCACTA >>30
こういう内容ゼロの事を言ってる意識高い系が普及を邪魔してる。自身が”何度も使えば配列地獄になるけど”と
認めてるにも関わらず、最初からイテレータを使えばと先に言ってることをそのまま返す
何が”したがって”なのか全然分からんが、説明した気になり、”チェーンを使うかの話に配列は関係ない”と
まとめる。そもそもチェーンを批判なんてしてない(対象によりけり高階関数の連続使用はメモリーを圧迫する
可能性があるということだけ)それとも言い負かしたいだけの気持ち悪さをそんなに使用者に伝えたいのか?
こういう内容ゼロの事を言ってる意識高い系が普及を邪魔してる。自身が”何度も使えば配列地獄になるけど”と
認めてるにも関わらず、最初からイテレータを使えばと先に言ってることをそのまま返す
何が”したがって”なのか全然分からんが、説明した気になり、”チェーンを使うかの話に配列は関係ない”と
まとめる。そもそもチェーンを批判なんてしてない(対象によりけり高階関数の連続使用はメモリーを圧迫する
可能性があるということだけ)それとも言い負かしたいだけの気持ち悪さをそんなに使用者に伝えたいのか?
2021/11/08(月) 07:59:01.69ID:SITQ70se
>>25
君が二つの全く異なるmap()をゴチャ混ぜにして皆を騙して混乱させているだけだ
我々はfor文で回すかイテレータをチェーンするかの話をしている
君が持ち出した[T; N]::map()は配列を配列に変換するのみでイテレータと一切関係ない
我々はmap()に関しては一貫してIterator::map()の話しかしていない
君が二つの全く異なるmap()をゴチャ混ぜにして皆を騙して混乱させているだけだ
我々はfor文で回すかイテレータをチェーンするかの話をしている
君が持ち出した[T; N]::map()は配列を配列に変換するのみでイテレータと一切関係ない
我々はmap()に関しては一貫してIterator::map()の話しかしていない
36デフォルトの名無しさん
2021/11/08(月) 08:32:39.74ID:fuBvo+92 ほんとここに来るやつは皆を騙す詐欺師の気持ちや悪い奴ばかり、一切関係ないぞ!
2021/11/08(月) 10:16:54.73ID:csyRALBm
どんなに適当に書いてもコンパイラさんがうまいこと最適化してくれるのでヨシ!
38デフォルトの名無しさん
2021/11/08(月) 10:32:52.09ID:xhkp7neH 最初から大して違いも出ないが、分かりやすさを重視するなら高階関数かな?
これはこう書け!と口煩くいってくる奴が理解できないけど…
でも裾野を広げるためには未熟で冗長なコードでも許容しなきゃね、1つもfor無しで
デカいプロジェクトを書くことなんて無いし、趣味でやってるだけなら縛りもありだが
これはこう書け!と口煩くいってくる奴が理解できないけど…
でも裾野を広げるためには未熟で冗長なコードでも許容しなきゃね、1つもfor無しで
デカいプロジェクトを書くことなんて無いし、趣味でやってるだけなら縛りもありだが
2021/11/08(月) 10:39:48.75ID:XWIn4U6b
高階関数でかくと並列化しやすいからそう書いてる
2021/11/08(月) 11:16:30.19ID:NiBBbin2
>>39
rayonなどに移行しやすいという意味?
rayonなどに移行しやすいという意味?
41デフォルトの名無しさん
2021/11/08(月) 11:23:59.38ID:OCI2yhfb rustの得意とする高パフォーマンス領域だとactix(-web)なんかはスレッド数=物理コア数で
下手に並列化しないほうがrequest/secは高いから、標準の高階関数も並列にはなっていない
訳で、バッチ処理みたいなその時に他の処理が走ってなくて、如何に処理時間を短くするか
というプログラムなら最初からRayonとか最初に導入してそう…
状態共有しない並列起動だけなら、thread::spawn(|| { for i in 0..x {...} }でも比較的に
簡単に出来るが、そういう意味では無いんだろう
下手に並列化しないほうがrequest/secは高いから、標準の高階関数も並列にはなっていない
訳で、バッチ処理みたいなその時に他の処理が走ってなくて、如何に処理時間を短くするか
というプログラムなら最初からRayonとか最初に導入してそう…
状態共有しない並列起動だけなら、thread::spawn(|| { for i in 0..x {...} }でも比較的に
簡単に出来るが、そういう意味では無いんだろう
2021/11/08(月) 11:28:09.63ID:hB1EvZ1K
さすが長文w
中身がナッシング
中身がナッシング
2021/11/08(月) 12:29:17.17ID:QzkUvy+x
>皆を騙す詐欺師の気持ち悪い奴ばかり
都合悪くなると話題変えて逃げるしな
都合悪くなると話題変えて逃げるしな
2021/11/08(月) 12:33:26.36ID:4QnDXIIG
async/awaitが高階関数と(今の所)相性良くない
45デフォルトの名無しさん
2021/11/08(月) 12:45:54.28ID:ODzJsaPg 話題変えて逃げてんじゃねーよ!カス!
2021/11/08(月) 13:17:11.03ID:NiBBbin2
2021/11/08(月) 13:48:44.02ID:vASCcAjA
静的チェックでオールOKみたいな言語って意識高い系のバカを呼び寄せやすいんだよ。
奴らは動的テストなんてしたくないって意識をすぐ誤魔化す癖がついてる。
奴らは動的テストなんてしたくないって意識をすぐ誤魔化す癖がついてる。
2021/11/08(月) 14:48:38.73ID:xhY6YpeY
ストローマンがあらわれた
2021/11/08(月) 14:51:34.92ID:vASCcAjA
自分のことを言われて怒っちゃったのか。
わかりやすいね。
わかりやすいね。
2021/11/08(月) 14:53:05.69ID:M7ed0MM2
51デフォルトの名無しさん
2021/11/08(月) 15:29:22.26ID:GGqoyJW12021/11/08(月) 17:38:09.25ID:7WV3o+af
Vecに入ったi32(空っぽの可能性もあり)の平均を計算するのってどうするのが一番スマート?
53デフォルトの名無しさん
2021/11/08(月) 17:43:46.40ID:Chf4/Vgn 高階関数使う
2021/11/08(月) 20:19:03.35ID:QIO9hdEn
副作用持つときはfor文でそれ以外はメソッドチェーン繋げてやります
2021/11/08(月) 21:14:06.85ID:6BzlB5w0
>>34
イテレータの高階関数の連続使用でメモリーを圧迫することはないと思います
各イテレータ自体はコンパクトな構造体ですし高階関数自体の処理も基本的にはメモリーを圧迫するものではありません
ただし全ての要素を受け取らないと算出できない物もあるため一時的に長いVecを使うことになるイテレータもあります
この場合はイテレータを用いずに自分でforなどを回す方法をとっても同様にして一時的に長いVecを使うことになるでしょう
イテレータの高階関数の連続使用でメモリーを圧迫することはないと思います
各イテレータ自体はコンパクトな構造体ですし高階関数自体の処理も基本的にはメモリーを圧迫するものではありません
ただし全ての要素を受け取らないと算出できない物もあるため一時的に長いVecを使うことになるイテレータもあります
この場合はイテレータを用いずに自分でforなどを回す方法をとっても同様にして一時的に長いVecを使うことになるでしょう
2021/11/08(月) 21:14:39.00ID:IC/lLBzS
そういや平均求めるメソッドってstd::iterにもitertoolsにもないんか?
2021/11/08(月) 21:38:29.05ID:NiBBbin2
>>47
Rustには動的テストを容易にする仕組みが入ってるしRustの話ではなさそうだ
Rustには動的テストを容易にする仕組みが入ってるしRustの話ではなさそうだ
2021/11/08(月) 21:38:34.43ID:3AO0oG+L
そんな簡単な実装を一々stdに入れてたら、糞関数だらけのLLライクになるじゃん?
2021/11/09(火) 04:01:57.70ID:d6arxLIn
2021/11/09(火) 20:24:06.75ID:E/uEHC7F
>>59
こんな感じでsumとcountを同時に計算かな
trait Average<T> {
fn average(self) -> T;
}
impl<I: Iterator<Item=T>, T: Zero + One + Add<Output=T> + Div<Output=T>> Average<T> for I {
fn average(self: I) -> T {
let (cnt, sum): (T, T) = self.fold((Zero::zero(), Zero::zero()), |(cnt, sum), n| (cnt + One::one(), sum + n));
sum / cnt
}
}
fn main() {
assert_eq!(500, (1..1000).into_iter().average());
assert_eq!(6.8, vec![2.3, 8.7, 9.4].into_iter().average());
assert_eq!(33, [1, 3, 5, 7, 9].into_iter().map(|n| n*n).average());
}
こんな感じでsumとcountを同時に計算かな
trait Average<T> {
fn average(self) -> T;
}
impl<I: Iterator<Item=T>, T: Zero + One + Add<Output=T> + Div<Output=T>> Average<T> for I {
fn average(self: I) -> T {
let (cnt, sum): (T, T) = self.fold((Zero::zero(), Zero::zero()), |(cnt, sum), n| (cnt + One::one(), sum + n));
sum / cnt
}
}
fn main() {
assert_eq!(500, (1..1000).into_iter().average());
assert_eq!(6.8, vec![2.3, 8.7, 9.4].into_iter().average());
assert_eq!(33, [1, 3, 5, 7, 9].into_iter().map(|n| n*n).average());
}
2021/11/09(火) 22:53:03.40ID:yHbe3Xjs
オーバーフローしないように型を選択することとか、
汎用的に使えて問題を避けることを考えたら平均を計算するのってそんなに簡単な話ではないと思う。
汎用的に使えて問題を避けることを考えたら平均を計算するのってそんなに簡単な話ではないと思う。
62デフォルトの名無しさん
2021/11/10(水) 08:15:17.85ID:BLadVH6y stats::median
今でもfilter使えだとかうっせーのばっかり、標準ライブラリは小さくて良いYO
https://lib.rs/science/math
statrs-dev/statrsとか好きなの引っ張ってきて入れろよ?平均じゃなくてもさ
今でもfilter使えだとかうっせーのばっかり、標準ライブラリは小さくて良いYO
https://lib.rs/science/math
statrs-dev/statrsとか好きなの引っ張ってきて入れろよ?平均じゃなくてもさ
2021/11/12(金) 17:23:46.15ID:pYLNCtl5
Vecとかに入った複数のtokio::task::JoinHandleをjoinするのはどうやるんでしょうか?
2021/11/12(金) 20:00:37.76ID:PXROpwUc
thread::JoinHandleは並列で(マルチスレッドとなり)
join()で待つ
task::JoinHandleは非同期で(シングルスレッド時は並行、マルチスレッド時は並列となり)
awaitで待つ
join()で待つ
task::JoinHandleは非同期で(シングルスレッド時は並行、マルチスレッド時は並列となり)
awaitで待つ
2021/11/12(金) 21:00:47.58ID:CuMBVxkM
futures::future::join_allでいいんじゃね
2021/11/12(金) 23:59:03.69ID:BY1dkyYH
task::JoinHandleの方はFuture trait実装なので
列挙ならfutures::join!(f1,f2,f3,...)マクロ
VecならIntoIteratorに対応のjoin_all(v) >>65
列挙ならfutures::join!(f1,f2,f3,...)マクロ
VecならIntoIteratorに対応のjoin_all(v) >>65
2021/11/17(水) 00:04:41.47ID:6Xk/Jjaa
おいウンコ引き取りに来いよ
2021/11/20(土) 19:33:51.68ID:i03LC++E
let mut a = 'a';
let mut d = 'd';
match 'b' {
a..=d => { println!("true") }
_ => { println!("false") }
}
matchでcharの範囲指定ができるからって試したんだけど、
変数に入れたcharだと範囲指定ってできないの?
これだとあんまり意味ないような
let mut d = 'd';
match 'b' {
a..=d => { println!("true") }
_ => { println!("false") }
}
matchでcharの範囲指定ができるからって試したんだけど、
変数に入れたcharだと範囲指定ってできないの?
これだとあんまり意味ないような
2021/11/20(土) 20:32:13.75ID:iQUqB4pW
パターンには代入される側の変数しか書けないけどガードは自由自在
fn test(b: char) -> bool {
let a = 'a';
let d = 'd';
match b {
_ if a <= b && b <= d => true,
_ => false,
}
}
fn main() {
assert_eq!(test('b'), true);
assert_eq!(test('x'), false);
}
fn test(b: char) -> bool {
let a = 'a';
let d = 'd';
match b {
_ if a <= b && b <= d => true,
_ => false,
}
}
fn main() {
assert_eq!(test('b'), true);
assert_eq!(test('x'), false);
}
2021/11/20(土) 20:43:54.76ID:iQUqB4pW
そして範囲指定を使いたいんだったらこう
_ if (a..=d).contains(&b) => true,
_ if (a..=d).contains(&b) => true,
2021/11/20(土) 20:49:00.01ID:iQUqB4pW
bのところが式かも知れないのでxにマッチさせてこの方がベターか
x if (a..=d).contains(&x) => true,
x if (a..=d).contains(&x) => true,
2021/11/20(土) 21:28:17.44ID:i03LC++E
>>69
ありがとう
if (a..=b).contains(&c) { println!("true") } else { println!("false"); };
って感じで試して見たけど、ガードで
(a..=b).contains(&c)にすればよさげだとわかった
ありがとう
if (a..=b).contains(&c) { println!("true") } else { println!("false"); };
って感じで試して見たけど、ガードで
(a..=b).contains(&c)にすればよさげだとわかった
2021/11/21(日) 01:21:54.59ID:VYuGYhJz
Rangeを含むジェネリックな関数を作りたいのですが例えば単純化した例
fn ntimes_print<T: num::Integer>(n: T, s: &str) {
(0..n).for_each(|_| print!("{}", s));
}
ここでRangeのnがexpected integerと言われエラーになってしまい
上記のように型Tにnum::Integerトレイトを制約してみましたが上手くいきません
どうすれば型TとジェネリックのままRangeを使えるでしょうか?
fn ntimes_print<T: num::Integer>(n: T, s: &str) {
(0..n).for_each(|_| print!("{}", s));
}
ここでRangeのnがexpected integerと言われエラーになってしまい
上記のように型Tにnum::Integerトレイトを制約してみましたが上手くいきません
どうすれば型TとジェネリックのままRangeを使えるでしょうか?
2021/11/21(日) 01:26:47.07ID:mkw0m2hl
>>73
複数のトレイトは + で繋げることができるんやで
複数のトレイトは + で繋げることができるんやで
2021/11/21(日) 01:30:30.33ID:VYuGYhJz
2021/11/21(日) 02:02:32.44ID:VYuGYhJz
格闘しているうちにコンパイラがstableじゃダメだとかfeature指定しろとか無茶を言って来るので従ってnightlyにしたりfeature指定したりしたところようやく動いたのですが何か変ですよね
2021/11/21(日) 02:16:44.28ID:qtUeCPjG
うーん
引数に繰り返す回数渡せばいいような気がするんだけどそう簡単じゃないのね
引数に繰り返す回数渡せばいいような気がするんだけどそう簡単じゃないのね
2021/11/21(日) 02:30:42.73ID:VYuGYhJz
nightlyにせずstableのままで範囲指定nをジェネリック化できた方いましたらやり方教えて下さい
2021/11/21(日) 02:59:34.97ID:mkw0m2hl
>>75
ドキュメントをみるかぎり PartialOrd が要求されているでよ
ドキュメントをみるかぎり PartialOrd が要求されているでよ
2021/11/21(日) 03:09:03.92ID:qtUeCPjG
やりたいことってこんな感じ?
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f97e7a0bd7775b88065da30bcf6a6a01
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f97e7a0bd7775b88065da30bcf6a6a01
2021/11/21(日) 04:34:14.82ID:VYuGYhJz
2021/11/21(日) 10:25:42.94ID:szj4saah
リテラル`0`の問題とstd::iter::Stepがunstableなのと2つ問題を解決する必要がある
fn ntimes_print<T>(n: T, s: &str)
where T: num::Integer + num::ToPrimitive + Clone
{
num::range(T::zero(), n).for_each(|_| print!("{}", s));
}
fn ntimes_print<T>(n: T, s: &str)
where T: num::Integer + num::ToPrimitive + Clone
{
num::range(T::zero(), n).for_each(|_| print!("{}", s));
}
2021/11/21(日) 11:02:09.61ID:VYuGYhJz
やはり..を使う限りstableでは無理でnightlyでないと以下のような素朴な実装も無理ということでしょうか
少し例を実用的に変えてみましたがトレイト境界(制約)を最小限で以下のようなコードでnightlyだと動いています
#![feature(step_trait)]
fn main() {
let n = 5; // 任意の整数型
n.times(|n| println!("OK {}", n));
}
trait Times<T: Sized> {
fn times<F>(self, f: F) where F: FnMut(T) -> ();
}
impl<T> Times<T> for T where T: num::Zero + std::iter::Step {
fn times<F>(self: T, f: F) where F: FnMut(T) -> () {
(num::Zero::zero()..self).for_each(f);
}
}
少し例を実用的に変えてみましたがトレイト境界(制約)を最小限で以下のようなコードでnightlyだと動いています
#![feature(step_trait)]
fn main() {
let n = 5; // 任意の整数型
n.times(|n| println!("OK {}", n));
}
trait Times<T: Sized> {
fn times<F>(self, f: F) where F: FnMut(T) -> ();
}
impl<T> Times<T> for T where T: num::Zero + std::iter::Step {
fn times<F>(self: T, f: F) where F: FnMut(T) -> () {
(num::Zero::zero()..self).for_each(f);
}
}
2021/11/21(日) 12:10:20.71ID:qtUeCPjG
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3702e2291f04ef5e40bd5310079972b1
2021/11/21(日) 15:03:50.15ID:szj4saah
2021/11/21(日) 16:08:27.58ID:VYuGYhJz
>>85
凄い!stableで..で動きました!ありがとう!
impl<T> Times<T> for T where T: num::Zero, std::ops::Range<T>: Iterator<Item=T> {
fn times<F>(self: T, f: F) where F: FnMut(T) -> () {
(num::Zero::zero()..self).for_each(f);
}
}
凄い!stableで..で動きました!ありがとう!
impl<T> Times<T> for T where T: num::Zero, std::ops::Range<T>: Iterator<Item=T> {
fn times<F>(self: T, f: F) where F: FnMut(T) -> () {
(num::Zero::zero()..self).for_each(f);
}
}
87デフォルトの名無しさん
2021/11/21(日) 18:59:28.56ID:a8amZ/lG 更にtimes()自体をイテレータにしてしまえば汎用的になるだけでなく
それらトレイト境界などのコードの記述も魔法のように消えて短くなる
fn main() {
let n = 5; // 任意の整数型
n.times().for_each(|n| println!("OK {}", n));
}
trait Times<T: Sized> {
fn times(self) -> std::ops::Range<T>;
}
impl<T: num::Zero> Times<T> for T {
fn times(self: T) -> std::ops::Range<T> {
num::Zero::zero()..self
}
}
これだけで動作する
それらトレイト境界などのコードの記述も魔法のように消えて短くなる
fn main() {
let n = 5; // 任意の整数型
n.times().for_each(|n| println!("OK {}", n));
}
trait Times<T: Sized> {
fn times(self) -> std::ops::Range<T>;
}
impl<T: num::Zero> Times<T> for T {
fn times(self: T) -> std::ops::Range<T> {
num::Zero::zero()..self
}
}
これだけで動作する
2021/11/21(日) 20:22:13.92ID:ekMm5ue5
timesなら精々u64::MAX回も繰り返すことなさそうだしTからu64に変換するのではだめなの?
2021/11/21(日) 20:32:22.18ID:VYuGYhJz
2021/11/22(月) 10:01:45.21ID:YMaXH3oe
指定するトレイト境界が減った代わりにAPIが劣化してる
2021/11/22(月) 11:46:24.84ID:EEj8G+es
>>90
イテレータ版の方がfor_each以外とも組み合わせられるからAPIとして良いと思う
>>87
しかしトレイト境界でnum::Zeroしか求められないのはstd::ops::Range周りの設計がおかしいと思われる
普通に実装すれば初期値(num::Zero)に増分(num::One)を加えて(ops::Add)いって比較(ops::PartialOrd)が必要となる
実際にnum::rangeによるイテレータ版times()の実装は Clone + PartialOrd + num::Zero + num::One となる
fn main() {
let n = 5; // 任意の整数型
n.times().for_each(|n| println!("OK {}", n));
}
trait Times<T: Sized> {
fn times(self) -> num::iter::Range<T>;
}
impl<T: Clone + PartialOrd + num::Zero + num::One> Times<T> for T {
fn times(self: T) -> num::iter::Range<T> {
num::range(T::zero(), self)
}
}
イテレータ版の方がfor_each以外とも組み合わせられるからAPIとして良いと思う
>>87
しかしトレイト境界でnum::Zeroしか求められないのはstd::ops::Range周りの設計がおかしいと思われる
普通に実装すれば初期値(num::Zero)に増分(num::One)を加えて(ops::Add)いって比較(ops::PartialOrd)が必要となる
実際にnum::rangeによるイテレータ版times()の実装は Clone + PartialOrd + num::Zero + num::One となる
fn main() {
let n = 5; // 任意の整数型
n.times().for_each(|n| println!("OK {}", n));
}
trait Times<T: Sized> {
fn times(self) -> num::iter::Range<T>;
}
impl<T: Clone + PartialOrd + num::Zero + num::One> Times<T> for T {
fn times(self: T) -> num::iter::Range<T> {
num::range(T::zero(), self)
}
}
2021/11/22(月) 12:13:59.22ID:qBbb57Hy
わざわざ外部crateと独自trait使って
n.times().for_each(f)にするくらいなら
(0..n).for_each(f)で十分
n.times().for_each(f)にするくらいなら
(0..n).for_each(f)で十分
2021/11/22(月) 12:33:40.60ID:EEj8G+es
>>92
それでは最初の条件のジェネリックを満たせていない
>>88
状況によってはそのように強引にu64へ変換できても対応できなくなるケースもある
例えば単純な例として文字'x'からのみなる文字列による型Xを考えてみよう
#[derive(Debug,Clone,PartialEq,PartialOrd)]
struct X(String);
impl X {
fn new(s: &str) -> Self {
if !s.chars().all(|c| c == 'x') {
panic!("not x");
}
X(s.to_string())
}
}
これで文字'x'以外は使えない文字列の型が出来上がり
あとは>>91で必要なZeroとOneとAddを定義すれば動くはず
impl num::Zero for X {
fn zero() -> X { X::new("") }
fn is_zero(&self) -> bool { self.0 == "" }
}
impl num::One for X {
fn one() -> X { X::new("x") }
}
impl std::ops::Add for X {
type Output = X;
fn add(self, rhs: X) -> X { X(self.0.clone() + &(rhs.0)) }
}
それでは最初の条件のジェネリックを満たせていない
>>88
状況によってはそのように強引にu64へ変換できても対応できなくなるケースもある
例えば単純な例として文字'x'からのみなる文字列による型Xを考えてみよう
#[derive(Debug,Clone,PartialEq,PartialOrd)]
struct X(String);
impl X {
fn new(s: &str) -> Self {
if !s.chars().all(|c| c == 'x') {
panic!("not x");
}
X(s.to_string())
}
}
これで文字'x'以外は使えない文字列の型が出来上がり
あとは>>91で必要なZeroとOneとAddを定義すれば動くはず
impl num::Zero for X {
fn zero() -> X { X::new("") }
fn is_zero(&self) -> bool { self.0 == "" }
}
impl num::One for X {
fn one() -> X { X::new("x") }
}
impl std::ops::Add for X {
type Output = X;
fn add(self, rhs: X) -> X { X(self.0.clone() + &(rhs.0)) }
}
2021/11/22(月) 12:45:37.77ID:EEj8G+es
>>93の続き
ところがnumクレートのOneは不必要に掛け算のMulも要求してきた
仕方ないので呼び出したらパニックするimplを加える
impl std::ops::Mul for X {
type Output = X;
fn mul(self, _rhs: X) -> X {
panic!("mul() for X")
}
}
さらになぜかnum::ToPrimitiveも要求してきたのでこれもパニック実装する
impl num::ToPrimitive for X {
fn to_i64(&self) -> Option<i64> {
panic!("to_i64() for X")
}
fn to_u64(&self) -> Option<u64> {
panic!("to_u64() for X")
}
}
これで>>91のnum::range利用イテレータ版times()が動くはず
そういえばDisplay実装を忘れたのでDebug表示
fn main() {
let n = X::new("xxxxx");
n.times().for_each(|n| println!("OK {:?}", n));
}
実行結果:
OK X("")
OK X("x")
OK X("xx")
OK X("xxx")
OK X("xxxx")
ちゃんと数値型以外でも動きました
ところがnumクレートのOneは不必要に掛け算のMulも要求してきた
仕方ないので呼び出したらパニックするimplを加える
impl std::ops::Mul for X {
type Output = X;
fn mul(self, _rhs: X) -> X {
panic!("mul() for X")
}
}
さらになぜかnum::ToPrimitiveも要求してきたのでこれもパニック実装する
impl num::ToPrimitive for X {
fn to_i64(&self) -> Option<i64> {
panic!("to_i64() for X")
}
fn to_u64(&self) -> Option<u64> {
panic!("to_u64() for X")
}
}
これで>>91のnum::range利用イテレータ版times()が動くはず
そういえばDisplay実装を忘れたのでDebug表示
fn main() {
let n = X::new("xxxxx");
n.times().for_each(|n| println!("OK {:?}", n));
}
実行結果:
OK X("")
OK X("x")
OK X("xx")
OK X("xxx")
OK X("xxxx")
ちゃんと数値型以外でも動きました
2021/11/22(月) 15:04:22.59ID:UzgCqcLK
>>93
>それでは最初の条件のジェネリックを満たせていない
ジェネリックにしたければ(T::zero()..n).for_each(f)と書けばいいだけでしょ
単にRangeを返すだけのメソッドを手間かけて微妙に抽象化しても周りが迷惑するだけだぞ
>それでは最初の条件のジェネリックを満たせていない
ジェネリックにしたければ(T::zero()..n).for_each(f)と書けばいいだけでしょ
単にRangeを返すだけのメソッドを手間かけて微妙に抽象化しても周りが迷惑するだけだぞ
2021/11/22(月) 15:23:28.68ID:EEj8G+es
2021/11/22(月) 19:21:50.63ID:fRCpO7Rh
どうしてもstableでやりたいという話ならRangeとStepを独自に用意するしかなさそう
n..mという表記は使えないが、n.times()なら支障なく実装できるかと
自分なら以下みたいに書くけどね
(T: From<i32> + PartialOrd が前提)
(0..).map(T::from).take_while(move ¦x¦ x<n)
n..mという表記は使えないが、n.times()なら支障なく実装できるかと
自分なら以下みたいに書くけどね
(T: From<i32> + PartialOrd が前提)
(0..).map(T::from).take_while(move ¦x¦ x<n)
98デフォルトの名無しさん
2021/11/22(月) 19:36:28.33ID:3Rtka3dv なるほどね
2021/11/22(月) 19:55:09.41ID:5egSOJea
100デフォルトの名無しさん
2021/11/22(月) 20:04:43.45ID:VyYbXHRo C++じゃないんだから不毛な型パズルはやめろ
101デフォルトの名無しさん
2021/11/22(月) 20:25:52.53ID:gBMgBg1g C++よりマシ
102デフォルトの名無しさん
2021/11/22(月) 20:56:45.47ID:MJpN6tlo 意味のない例で延々とよくやるわ
103デフォルトの名無しさん
2021/11/22(月) 21:02:15.85ID:FLi/1Joa カスタムな型ならRangeよりイテレータ対応が先
104デフォルトの名無しさん
2021/11/22(月) 21:09:17.05ID:fRCpO7Rh StepがunstableなのはさておきFromLiteralみたいなトレイトがあるとZeroやOneの出番が減ってうれしいのかね
T: FromLiteralの時に整数リテラルがT型の値として解釈されるようになるようなイメージ
T: FromLiteralの時に整数リテラルがT型の値として解釈されるようになるようなイメージ
105デフォルトの名無しさん
2021/11/22(月) 21:58:50.69ID:FLi/1Joa try_into()でできるよ
106デフォルトの名無しさん
2021/11/22(月) 22:09:34.28ID:fRCpO7Rh 言葉足らずでしたね
struct Foo;
が FromLiteral を実装しているときに
let n: T = 123;
というコードを書くとコンパイラが
let n = T::from_literal("123");
といったコードに変換してくれるイメージ
from_literalはconst fnにできてコンパイル時にエラー検出できるとベター
struct Foo;
が FromLiteral を実装しているときに
let n: T = 123;
というコードを書くとコンパイラが
let n = T::from_literal("123");
といったコードに変換してくれるイメージ
from_literalはconst fnにできてコンパイル時にエラー検出できるとベター
107デフォルトの名無しさん
2021/11/22(月) 22:10:11.00ID:fRCpO7Rh >>106
TはFooの間違い
TはFooの間違い
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 中国「国連安保理の許可なしに日本攻撃可能」 Xで旧敵国条項に言及… ★10 [BFU★]
- 高市首相告白「『なめられない服』を選ぶことに数時間を費やしました」「外交交渉でマウント取れる服、買わなくてはいかんかもなぁ」★2 [ぐれ★]
- 首相官邸前で「戦争あおるな」 台湾有事巡る答弁に抗議 ★2 [蚤の市★]
- 【野球】「地上波で放送しないWBC」は2軍選手中心で十分! 今こそネットフリックスに『ノー』を突き付けてほしい 江本氏が提言 [冬月記者★]
- 【高市リスク】立民・小西洋之参院議員「高市総理がとんでもない安全保障オンチで外交オンチ」 [ぐれ★]
- 『DOWNTOWN+』会員数50万人突破で見えてきた 松本人志の“月収4ケタ万円”驚愕収入 [阿弥陀ヶ峰★]
- 【フジテレビ】2025 FORMULA 1【NEXT】Lap599
- 福島競馬3回5日目
- こいせん 全レス転載禁止
- 巨専】
- 【DAZN】フォーミュラGP【F1 2 3 SF P】Lap1806
- とらせん IP
- 高市早苗、車のナンバーに37-77を愛用しているのが中国人に見つかる。盧溝橋事件の1937年7月7日を記念してか [624898991]
- 高市早苗、クマ対策に7400億円 [667744927]
- 【悲報】高市政権関係者「閣僚には円安が何かよくわかってない人がいる」「総理もデメリットを理解してない」🤤 [359965264]
- 【悲報】国連、日本を「先進国」から「高所得国」へ再分類、事実上の格下げ [769931615]
- 日本人「憲法9条があれば侵略されないって叫んでた売国左翼のゴミどもは今どんな気分?😂wwwwww」 [441660812]
- 【正義のミカタ】ほんこん さん「非核三原則は憲法に書いてない。核兵器持ったらええがな」 [201193242]
