公式
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(日) 13:02:12.62ID:BjoZRpKT
>前スレの質問「間違って同じ変数名つけたコード片突っ込んでしまった系だと他言語にあるらしい2重宣言エラーないの怖くないですか?」
他の言語でもスコープが違えば二重宣言エラーになりません
つまり他の言語でも意図しない同名変数ミスは同じように起き得ます
例えば以下はC言語の例
int c = 100;
int main() {
int c = 200;
{
int c = 300;
}
printf("%d\n", c); /* コンパイルは通って 200 となる */
}
Rustのシャドーイングは同じブロックスコープでも同名変数が通りますが
仮にミスで同名変数を付けたコードを挿入してしまったとしても
・その時点で先行の変数が既にライフタイム尽きていれば影響ゼロ
・その時点で先行の変数のライフタイムがあって割り込む形になる場合
・それ以降で二度の消費が発生して借用エラー発生となる可能性が高い
・先行の変数が一度も使われていない段階なら未使用warning発生
・型が違っていれば割り込む形であっても型違いでエラー発生
と影響ゼロもしくは引っかかる可能性が高いでしょう
>>4
おっしゃる通り、そもそも意図しない同名変数に気付かない時点で「その関数は長すぎ」ですね
他の言語でもスコープが違えば二重宣言エラーになりません
つまり他の言語でも意図しない同名変数ミスは同じように起き得ます
例えば以下はC言語の例
int c = 100;
int main() {
int c = 200;
{
int c = 300;
}
printf("%d\n", c); /* コンパイルは通って 200 となる */
}
Rustのシャドーイングは同じブロックスコープでも同名変数が通りますが
仮にミスで同名変数を付けたコードを挿入してしまったとしても
・その時点で先行の変数が既にライフタイム尽きていれば影響ゼロ
・その時点で先行の変数のライフタイムがあって割り込む形になる場合
・それ以降で二度の消費が発生して借用エラー発生となる可能性が高い
・先行の変数が一度も使われていない段階なら未使用warning発生
・型が違っていれば割り込む形であっても型違いでエラー発生
と影響ゼロもしくは引っかかる可能性が高いでしょう
>>4
おっしゃる通り、そもそも意図しない同名変数に気付かない時点で「その関数は長すぎ」ですね
2021/11/07(日) 13:03:26.24ID:GwJCd0Qm
ある値をちょっとだけ処理したものにどんな名前を付けたいかってのは、
まあ適した名前があるならそれに越したことは無いけど
同じ名前を付けることによってたいした違いはない、かつ以前の値にアクセスすることはもうないことが明示できるので
それはそれで使いようはあるよ。
以前の値にアクセスしないという意思を持ってシャドーイングを使うのでそれで困ることはない。
うっかりで同じ名前を付けてしまった場合も大抵の場合は型の違いとかで検出されるし。
まあ適した名前があるならそれに越したことは無いけど
同じ名前を付けることによってたいした違いはない、かつ以前の値にアクセスすることはもうないことが明示できるので
それはそれで使いようはあるよ。
以前の値にアクセスしないという意思を持ってシャドーイングを使うのでそれで困ることはない。
うっかりで同じ名前を付けてしまった場合も大抵の場合は型の違いとかで検出されるし。
7デフォルトの名無しさん
2021/11/07(日) 14:26:48.84ID:c7aT0NV0 何を問題にしてるのか分からんけど、コンパイラから見たら、同じ変数名宣言でも連番で構文解析しているわけで
ブロックスコープによりシャドーされても何ら関係ないが、インライン展開して最適化するrustコードだと問題が
出る場合もありうる。それとシャドーと以前の値にアクセスすることはもうない事は意味が違う
ブロックスコープによりシャドーされても何ら関係ないが、インライン展開して最適化するrustコードだと問題が
出る場合もありうる。それとシャドーと以前の値にアクセスすることはもうない事は意味が違う
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型の値として解釈されるようになるようなイメージ
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 中国国連大使「日本が中国に武力行使すると脅しをかけたのは初めて」 国連事務総長に書簡★4 [♪♪♪★]
- 【芸能】44歳・池脇千鶴、激変ぶりにネット衝撃 「まるで別人…」「変化が凄い!!」の声 [冬月記者★]
- 台湾有事での集団的自衛権行使に「賛成」が48.8%、「反対」が44.2% ★9 [♪♪♪★]
- なぜ立花孝志氏の言葉は信じられたのか…"異例の逮捕"が浮き彫りにした「SNSの危険な病理」 [ぐれ★]
- 中国「国連安保理の許可なしに日本攻撃可能」 Xで旧敵国条項に言及… ★15 [BFU★]
- 竹中平蔵氏、万博は大成功だったと持論 批判していた人々にチクリ「反省の弁の一つも聞きたい」 [バイト歴50年★]
