公式
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(日) 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の間違い
108デフォルトの名無しさん
2021/11/23(火) 07:57:08.78ID:9DtS3af5 ねこ
109デフォルトの名無しさん
2021/11/23(火) 10:28:33.41ID:8Ju98kPx https://github.com/rust-lang/team/pull/671
Coreチームがクソだからやめたった、ってこと?
Coreチームがクソだからやめたった、ってこと?
110デフォルトの名無しさん
2021/11/23(火) 13:56:03.32ID:b1gEfTjX const fnが言いたいだけやろ、だれが=演算子でcopyでもなく、言語上ないことになってるコンストラクタでもなく
そんな特異なトレイトを勝手に呼ぶのが嬉しいねん、なにがバター犬や
そんな特異なトレイトを勝手に呼ぶのが嬉しいねん、なにがバター犬や
111デフォルトの名無しさん
2021/11/23(火) 14:58:36.02ID:s6k3uLQ1■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 台湾有事での集団的自衛権行使に賛成48%、「反対」が44.2% ★2 [♪♪♪★]
- 中国「国連安保理の許可なしに日本攻撃可能」 Xで旧敵国条項に言及… ★13 [BFU★]
- 【サッカー】「国立ガラガラじゃん!」 「タダ券ばら撒かないんだっけ?」天皇杯決勝、6万7750人収容のスタンドに目立つ空席 [鉄チーズ烏★]
- 【淡路島】88歳男が好意を理由に60歳女性宅へ侵入か 「下の毛がほしい」不適切メモを残す ストーカー容疑で再逮捕 洲本市 [nita★]
- 【立憲民主党】「質問レベルの低さが立憲の存立危機事態」台湾有事発言を引き出した立憲“執拗追及”が波紋… [尺アジ★]
- 【NHK】受信料の未払い督促を10倍に強化… 支払い拒否が続くと民事手続きも 「カーナビも受信料いただきます」方針 [冬月記者★]
- 他サポ 2025-261
- 他サポ 2025-260
- 2025 SUPER FORMULA Lap18
- 【DAZN】フォーミュラGP【F1 2 3 SF P】Lap1807
- 京都競馬4回5日目エリザベス女王杯★3
- 福島競馬3回5日目
- 大河ドラマ『高市早苗』👈ありがちなこと [804169411]
- 高市ソルジャー、国連の敵国条項を持ち出すのは卑怯だと中国大使館にブチギレ [931948549]
- ネトウヨですら高市早苗首相をそんな評価してないとの声。SNSの熱量が少ない。 [253245739]
- 日本人の73%「中国が嫌い」日本の右傾化止まらない [165981677]
- 【高市悲報】中国、南アフリカを味方につけてイキる [614650719]
- 日本人の48%覚悟完了… [819729701]
