Rust part15 ..
[2ch|▼Menu]
2:デフォルトの名無しさん
22/05/12 18:30:00.00 cuIcFT6k.net
Rust The Book (日本語版)
URLリンク(doc.rust-jp.rs)
Rust edition guide (日本語版)
URLリンク(doc.rust-jp.rs)
Rust by example (日本語版)
URLリンク(doc.rust-jp.rs)
Rust cookbook (日本語版)
URLリンク(uma0317.github.io)
Rust API guideline (日本語版)
URLリンク(sinkuu.github.io)
Rust nomicon book (日本語版)
URLリンク(doc.rust-jp.rs)
Rust WASM book (日本語版)
URLリンク(moshg.github.io)
Rust embeded book (日本語版)
URLリンク(tomoyuki-nakabayashi.github.io)
Rust enbeded discovery (日本語版)
URLリンク(tomoyuki-nakabayashi.github.io)

3:デフォルトの名無しさん
22/05/12 18:30:13.50 cuIcFT6k.net
Rust CLI (Command Line Interface) apps Book
URLリンク(rust-cli.github.io)
Rust async-std Book
URLリンク(book.async.rs)
Rust The Unstable Book
URLリンク(doc.rust-lang.org)
Rust rustc Book
URLリンク(doc.rust-lang.org)
Rust Cargo Book
URLリンク(doc.rust-lang.org)
The Rust Reference
URLリンク(doc.rust-lang.org)
The Rust Standard Library
URLリンク(doc.rust-lang.org)

4:デフォルトの名無しさん
22/05/12 18:33:42.89 q5adbU17.net
c++スレやHaskelスレでああでもないこうでもないと実用性無視してごちゃごちゃ言ってたのがRustスレに移って来て
ああでもないこうでもないと不毛な話を繰り返してるだけなんだろうな…

5:デフォルトの名無しさん
22/05/12 21:06:22.42 EFEW+xd3.net
let mut >>1

6:デフォルトの名無しさん
22/05/12 23:07:25.38 13HXXMDq.net
ごちゃごちゃ戻り値の型さえ理解してないで書いてる

7:デフォルトの名無しさん
22/05/13 01:13:09.90 ufl1G9JB.net
またワッチョイなしですか

8:デフォルトの名無しさん
22/05/13 04:12:30.14 7BsdLj8J.net
>>6
ちゃんと理解しましょう

9:デフォルトの名無しさん
22/05/13 06:02:56 6rmlfzdI.net

もっとRustが普及しますように☆彡

10:デフォルトの名無しさん
22/05/13 18:17:33.08 9chxx07M.net
>>7
ワッチョイなんて飾りです

11:デフォルトの名無しさん
22/05/13 21:57:27.44 bn7J0pQ3.net
>>7
ワッチョイスレはすでにあるだろ

12:デフォルトの名無しさん
22/05/13 22:24:15.76 UR4E+9N6.net
>>8
正直言うと、俺たちは若い奴らが何やらワイワイさわいでCOBOLおじさんJAVAおじさん、C#おじさん扱いされないよう
カッコよさげだから、なんとなく雰囲気でRustを書いてるんだ。
でも、うまく言えないけど理解する必要性を全く感じない、下請けにおまえRustも分らんの?とマウントするのが夢なんだ
とやかく言われる筋合いは無い

13:デフォルトの名無しさん
22/05/13 23:48:07.30 uiqUB4xh.net
再帰的なmacroはaliasしても展開時に
元の名前のマクロを使おうとしてエラーになるんだがこれって避けられない?
use foo_crate::foo as bar;
bar!(…)
cannot find macro `foo` in this scope
this error originates in the macro `bar`

14:デフォルトの名無しさん
22/05/14 00:13:13.84 BgvoYA7m.net
>>13
foo! の定義中の foo! 呼び出しを $crate::foo!() みたいにすればいけるんじゃないかな

15:デフォルトの名無しさん
22/05/14 03:12:50.47 J3IrN4Ey.net
>>14
それだ、ありがとう

16:デフォルトの名無しさん
22/05/14 23:50:01.31 7gZW+FH0.net
前スレで出ていたこの上限チェックRangeFromだけど
fn countup<T>(start: T) -> impl Iterator<Item=T>
where T: Clone + TryFrom<usize> + num::CheckedAdd,
{
let one = T::try_from(1).ok().unwrap();
itertools::unfold((start, true), move |(n, is_first)| {
if *is_first {
*is_first = false;
Some(n.clone())
} else {
n.checked_add(&one)
.map(|new| { *n = new.clone(); new })
}
})
}
フラグ持たずにOptionで持ったほうがわかりやすくない?
fn countup<T>(start: T) -> impl Iterator<Item=T>
where T: Clone + TryFrom<usize> + num::CheckedAdd,
{
let one = T::try_from(1).ok().unwrap();
itertools::unfold(Some(start), move |n| {
let ret = n.clone();
if let &mut Some(ref m) = n {
*n = m.checked_add(&one);
}
ret
})
}

17:デフォルトの名無しさん
22/05/15 00:14:36.59 AindqZB4.net
複オジに毒されてるな
successors(Some(start), move |n| n.checked_add(&one))

18:デフォルトの名無しさん
22/05/15 02:25:52 /oKjcqbB.net
>>16
そのclone()は不要
トレイト境界からCloneを外せる

fn countup<T>(start: T) -> impl Iterator<Item=T>
where T: TryFrom<usize> + num::CheckedAdd,
{
let one = T::try_from(1).ok().unwrap();
itertools::unfold(Some(start), move |n| {
if let &mut Some(ref m) = n {
let mut next = m.checked_add(&one);
std::mem::swap(n, &mut next);
next
} else {
None
}
})
}

19:デフォルトの名無しさん
22/05/15 03:11:19.26 gyw6bZ1I.net
unfoldでなんでもできるからunfoldしか使わなくなってしまった人
いろいろな人

20:デフォルトの名無しさん
22/05/15 07:53:49.50 SgXGf86o.net
>>18
take()?でもっと簡潔に書ける
fn countup<T>(start: T) -> impl Iterator<Item=T>
where T: TryFrom<usize> + num::CheckedAdd,
{
let one = T::try_from(1).ok().unwrap();
itertools::unfold(Some(start), move |n| {
let cur = n.take()?;
*n = cur.checked_add(&one);
Some(cur)
})
}

21:デフォルトの名無しさん
22/05/15 08:07:10.15 SgXGf86o.net
>>19
unfoldは要点に絞って見やすい短縮記法として使われている
そのままunfoldを使わずに普通に構造体にimpl Iteratorする形へ置き換え可能なところがメリット
例えば>>20はそのまま機械的に以下へ展開できて同じく動作する
struct Countup<T> {
one: T,
n: Option<T>,
}
fn countup<T>(start: T) -> impl Iterator<Item=T>
where T: TryFrom<usize> + num::CheckedAdd,
{
Countup {
one: T::try_from(1).ok().unwrap(),
n: Some(start),
}
}
impl<T> Iterator for Countup<T>
where T: num::CheckedAdd,
{
type Item = T;
fn next(&mut self) -> Option<T> {
let cur = self.n.take()?;
self.n = cur.checked_add(&self.one);
Some(cur)
}
}
これだと長く冗長なので敢えてunfold利用版を記述することで要点のみに絞ることができる

22:デフォルトの名無しさん
22/05/15 10:14:06.42 2aUGzSw0.net
>>19
全部同じやつだぞ
一人二役で会話してる

23:デフォルトの名無しさん
22/05/15 10:54:06.34 +6kSxcdv.net
unfoldより関係が分かりにくくなるけど
キャプチャした変数を使うfrom_fnという手もある
fn countup<T>(start: T) -> impl Iterator<Item=T>
where T: TryFrom<usize> + num::CheckedAdd,
{
let mut n = Some(start);
let one = T::try_from(1).ok().unwrap();
std::iter::from_fn(move || {
let cur = n.take()?;
n = cur.checked_add(&one);
Some(cur)
})
}

24:デフォルトの名無しさん
22/05/15 10:54:14.40 duXfvT8B.net
大人が集まってくつろいでるところに
子供がガラッと入ってきて九九の暗唱しはじめたら
頑張ってるのがほほえましくて応援しちゃうでしょ
でも
大人がガラッと入ってきて九九の暗唱しはじめたら
ギョッとするし不安になってくるやろ
なぜそんなもんをお披露目しちゃうのか
なぜ得意げになって頑張ってるのかわからない
もういいよ!と単に言えばいいのか
続きはカーチャンに見えもらってね!と言えば良いのか
言って分かってもらえる気配もないので怖い

25:デフォルトの名無しさん
22/05/15 11:10:33.42 +6kSxcdv.net
今回はこれでもいい
fn countup<T>(start: T) -> impl Iterator<Item=T>
where T: TryFrom<usize> + num::CheckedAdd,
{
let one = T::try_from(1).ok().unwrap();
std::iter::successors(Some(start), move |n| n.checked_add(&one))
}

26:デフォルトの名無しさん
22/05/15 11:16:38.61 yna4qlqc.net
はちみつおじさん悔しそうwww

27:デフォルトの名無しさん
22/05/15 12:24:43.22 Q7/PweS0.net
九九と違って子供用のおもちゃプログラムでしか使えないコードなんだよなぁ

28:デフォルトの名無しさん
22/05/15 12:39:00.79 +mKsOYSe.net
代案出さずに文句だけつける万年野党みたいなやつがいるな

29:デフォルトの名無しさん
22/05/15 13:13:50.62 gyw6bZ1I.net
>>25
それまんま>>17やんけ

30:デフォルトの名無しさん
22/05/15 14:22:42.46 Cy+Jf1ha.net
九九のように簡単だという皆さま方に質問です
countup()が7通り(?)も色んな書き方が出てきて驚いたのですが
フィボナッチ数列だとどんな華麗なコードになりますか?
fn fibonacci<T>() -> impl Iterator<Item=T>
where T: TryFrom<usize> + num::CheckedAdd,
{
// ここを記述
}
出力仕様は一番ベーシックな0スタートとします
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

31:デフォルトの名無しさん
22/05/15 15:13:51.95 4TECkVdc.net
>>30
「Rustのお題スレ」でも立ててそっちでやってくれ

32:デフォルトの名無しさん
22/05/15 15:27:49.70 Cy+Jf1ha.net
>>31
難しくて解けないという表明ですか?
どういう点が難しかったのか教えてください

33:デフォルトの名無しさん
22/05/15 15:40:51.12 hZXiQ87C.net
教えてもらったsuccessorsを披露したくてしょうがない幼児メンタルwww
>>24の言う通りだな

34:デフォルトの名無しさん
22/05/15 15:49:35.48 AAncJnA8.net
>>33
successorsは適用範囲が非常に狭いので>>30の例には使えないはず

35:デフォルトの名無しさん
22/05/15 16:09:35.61 Cy+Jf1ha.net
>>33
ぜひそれを披露してやり方を教えてください

36:デフォルトの名無しさん
22/05/15 16:27:05.61 KYkY1Akn.net
フィボナッチ数列イテレータ前スレでだれかが書いてたでしょ
それじゃいかんの

37:デフォルトの名無しさん
22/05/16 07:04:42.44 nGMMRLLq.net
>>36
CopyやCloneを使っているから別問題だろう。
一般的にRustのプログラミングでは、
Copy(暗黙的な自動コピー)やClone(clone()による明示的な手動コピー)を使うと楽になるが、コストは高くなる。
そのため不要なclone()を見極めてそれを回避するプログラミングが出来るかどうか、というRustにおける根源的な話だろう。

38:デフォルトの名無しさん
22/05/16 07:28:24 JrfUQrzl.net
Copyのコストが高い?

39:デフォルトの名無しさん
22/05/16 08:00:50.97 nGMMRLLq.net
>>38
もちろんCopyは最もコストが高い。
個々のコスト自体は通常clone()と同じだが、常に自動的にclone()が起きるため最もコストが高くなる。

40:デフォルトの名無しさん
22/05/16 08:58:48.98 tFcB4vDN.net
複製おじさんはいつも自分勝手な妄想を「一般的には~」とか「皆は~」と言って自分を正当化しようとするよね

41:デフォルトの名無しさん
22/05/16 10:03:10.22 0DWo1Xps.net
>>40
間違いは誰にでもあるからまだいいんだが
指摘されても反省するどころかさらなる妄想を撒き散らすのがほんと迷惑

42:デフォルトの名無しさん
22/05/16 11:11:33 02kk6/+P.net
おじさん使いの人の自演がいつもよくわからん
唐突に妄想(?)を攻撃し出すが幻覚か何か見えてるのか

43:デフォルトの名無しさん
22/05/16 16:19:03.24 NE3SiQoq.net
>>39
Cloneのコストが高い型にCopyを実装するな

44:デフォルトの名無しさん
22/05/16 16:30:48.20 JLeK8lGd.net
Copyはコストが一番高いから出来る限り避けるべきだな
特にヒープを使うならCloneまでにしておくべき
可能ならばCloneも避けるべきだが

45:デフォルトの名無しさん
22/05/16 18:08:42.72 ThGcWJJo.net
Copyは所有権を複製するから最も高コスト(キリッ!!

46:デフォルトの名無しさん
22/05/16 18:10:04.46 ThGcWJJo.net
もはやどのレスもギャグにしか見えん
俺のしってるCopyとは確実に違う

47:デフォルトの名無しさん
22/05/16 18:38:28.59 qW5+0T97.net
今までで一番意味不明なこと言ってるな
Copyのコストが高いならmoveのコストはどうなるのよ

48:デフォルトの名無しさん
22/05/16 18:44:18.84 Mb2xQVjt.net
>>45
所有権に複製という概念はない
Copyをimplすると使われる時に値が自動的に複製される
そのためCopyは最も高コスト
>>46
君のレスがギャグにしか見えん

49:デフォルトの名無しさん
22/05/16 18:47:50.19 /5k6Bg80.net
Rust のムーブはビットパターンのコピーだもんな。
低レイヤの視点で見たらコピーと何の差も無い。
なるべく参照を使う場合にしても間接参照の実行コストとコピーの実行コストを天秤にかけてどちらが有利かは場合による。

50:デフォルトの名無しさん
22/05/16 18:55:12.38 W7mPHnnh.net
>>47
それは理解不足すぎるぜ
大文字のCopyはCopyトレイトを意味しCopyトレイトを実装するか否かの話だろ
moveは別方向の話であり比較対象にすらならない
比較するならば「Copy実装(必然的にClone)も実装」「Cloneのみ実装」「どちらも実装なし」の3つだな

51:デフォルトの名無しさん
22/05/16 19:00:08.16 GLqKLCqS.net
>>48
ギャグだと分からない人がいるとは想定していませんでした。
誤解を招いたのであれば申し訳ございません。

52:デフォルトの名無しさん
22/05/16 19:06:18.85 78bNbDCr.net
>>49
デタラメすぎ
ムーブでビットパターンのコピーは発生しない
ビットパターンのコピーが発生するのは引数の値渡し等であってムーブとは関係ない
さらに引数の値渡しでのでビットパターンのコピーとCopyのコピーも全く異なる
Copyのコピーはディープであって高コスト

53:デフォルトの名無しさん
22/05/16 19:08:38.74 NE3SiQoq.net
そもそもフィボナッチ数列イテレータなんて誰も求めてないので
前スレのだれかさんの実装に問題があると思うなら自分で勝手に改善してなさい
そしてその結果はここに貼らなくていいぞ

54:デフォルトの名無しさん
22/05/16 19:11:06.58 zgsMMZOB.net
「ヒープ使うならCloneまでにしとけ」
このセリフが一番刺さった

55:デフォルトの名無しさん
22/05/16 19:11:50.62 rHnqcaqs.net
>>52
おじさんマジかよwww

56:デフォルトの名無しさん
22/05/16 19:22:59.76 NE3SiQoq.net
>>54
Dropを実装する型はCopyを実装できないよ
BoxもRcもStringもVecもそもそもCopyを実装できないので、するかしないか考えること自体が無意味
どういう型にCopyを実装できるか、できないか、すべきかはdocsに書いてあるので
なんのかんの言う前にまずはこれを読もうね
URLリンク(doc.rust-lang.org)

57:デフォルトの名無しさん
22/05/16 19:37:56.79 tTdd7GU5.net
>>53
これだけCopyやCloneを理解していない連中が多い状況だと
>>30の質問に答えられるかどうかは最低限クリアすべきテストとして有用ではないか?
フィボナッチ自体はもちろんどうでもよい話だがCopyやCloneを避けるRustの基本ができるかどうかわかる点で

58:デフォルトの名無しさん
22/05/16 19:45:37.77 /5k6Bg80.net
>>52
じゃあムーブでなにが起こるとおもってんの?

59:デフォルトの名無しさん
22/05/16 19:54:25.89 SHnkjBGX.net
>>53
> フィボナッチ数列イテレータなんて誰も求めてない
それはそうなんだけど
唯一本人にとっては伝家の宝刀だから
少なくともこのスレいっぱいまでは引っ張って
何度も何度も参照するはず

60:デフォルトの名無しさん
22/05/16 20:38:11.38 NE3SiQoq.net
フィボナッチがどうでもいいならこの話は終わりです

61:デフォルトの名無しさん
22/05/16 20:45:13.08 Mz4z3EAu.net
関数の深いところから順に構造体をムーブで返していって
各関数で渡ってきた構造体のアドレスを表示させてみた
#[derive(Debug)]
struct S([i32; 100]);
fn main() {
let mut s1 = sub1(100);
s1.0[1] = 111;
println!("s1: {:p}", &s1);
println!("{s1:?}");
}
fn sub1(p: i32) -> S {
let q = p + 3;
let mut s2 = sub2(q);
s2.0[2] = p - 300;
println!("s2: {:p}", &s2);
s2
}
fn sub2(s: i32) -> S {
let t = s * 2;
let mut s3 = S([123; 100]);
s3.0[3] = t;
println!("s3: {:p}", &s3);
s3
}
s1もs2もs3もアドレスが一致
ムーブではアドレスそのままであり
ビットパターンのコピーが為されないという結論

62:デフォルトの名無しさん
22/05/16 20:58:36.88 qW5+0T97.net
>>50
"Copyのコストが高い" は Copy を実装する行為そのもののコストが高いと解釈すべきということ?
そんなばかな
>>52
ドキュメント読みましょうねー
URLリンク(doc.rust-lang.org)
> It’s important to note that in these two examples, the only difference is whether you are allowed to access x after the assignment.
> Under the hood, both a copy and a move can result in bits being copied in memory, although this is sometimes optimized away.
...
> The behavior of Copy is not overloadable; it is always a simple bit-wise copy.
...
> The implementation of Clone can provide any type-specific behavior necessary to duplicate values safely.
> For example, the implementation of Clone for String needs to copy the pointed-to string buffer in the heap.

63:デフォルトの名無しさん
22/05/16 21:06:43.52 qW5+0T97.net
>>61
アドレスが同じか否かでコピーの有無を判断する意味はよくわからんが
その理屈だとこのコードだと違うアドレスが表示されるからビットパターンのコピーがされてるって結論になるのか?
#[derive(Debug)]
struct S([i32; 100]);
fn main() {
let mut s1 = S([0; 100]);
println!("s1: {:p}", &s1);
let s2 = s1;
println!("s2: {:p}", &s2);
}

64:デフォルトの名無しさん
22/05/16 21:07:20.55 f/Xu02FO.net
>>61
struct S {}
fn main() {
let s1 = S{};
println!("s1: {:p}", &s1);
let s2 = s1;
println!("s2: {:p}", &s2);
}

65:デフォルトの名無しさん
22/05/16 21:08:00.98 f/Xu02FO.net
ごめん被った。やっぱそう思うよね。

66:デフォルトの名無しさん
22/05/16 21:16:19.81 9Ab93Lwf.net
>>56
ちょっとw
なんで刺さったのか少しは考えてよww
ギャグゴロシめ

67:デフォルトの名無しさん
22/05/16 21:19:28.47 51EzJkQ/.net
>>61
>>63
その二つの相異なる結果を見るとビットパターンのコピーはムーブ以外の要因で起きている??

68:デフォルトの名無しさん
22/05/16 21:30:56.46 W905eBh/.net
>>57
一番分かってないお前が言うなよw

69:デフォルトの名無しさん
22/05/16 21:38:19.38 /vD2A9J9.net
>>61
高コストなCopyも実装してから確認してみてねww

70:デフォルトの名無しさん
22/05/16 21:38:29.32 NE3SiQoq.net
>>66
ごめんよ
刺さったって「ためになった」みたいな意味で言ってるのかと思ったよ
てっきりオジの自演かと

71:デフォルトの名無しさん
22/05/16 21:39:12.01 DoCeaK1g.net
>>67
デバッグビルドだけじゃなくリリースビルドでも確認してねw

72:デフォルトの名無しさん
22/05/16 21:42:44.19 51EzJkQ/.net
>>71
リリースモードでもどちらも同じ結果

73:デフォルトの名無しさん
22/05/16 21:49:25.30 sElCPUyn.net
>>72
ごめんよー
>>64と間違えた

74:デフォルトの名無しさん
22/05/16 23:46:37.66 jfEIc0ZW.net
このスレはいつもおかしい人間たちが集まってるな
Rustの何が人を狂わせるんだ?

75:デフォルトの名無しさん
22/05/17 00:09:43.95 HbNyXd2X.net
おじさんイジリ飽きたので結論いっておく
Copyもmoveもスタックの中身をコピーしてるのは同じ
最適化によって不要なコピーが除去されるかどうかはLLVM次第
でかい配列やでかい構造体などの極一部を除けばCopyは参照の受け渡しよりも低コスト
ついでに言うと&TもCopy

76:デフォルトの名無しさん
22/05/17 00:26:01.61 +9bLcV37.net
>>75
頭悪すぎ
Copyが低コストなのではなく
低コストなものだけにCopyが実装されている
なぜならCopyは高コストであるため

77:デフォルトの名無しさん
22/05/17 02:09:56.03 2XRLgT14.net
>>76
ここでいうCopyのコストって具体的にどういう操作のコストのこと言ってる?
構造体データのbitwise-copyのこと?それとも別の何か?
Cloneやmoveの場合にそのコストは発生しないと主張しているの?

78:デフォルトの名無しさん
22/05/17 02:13:55.30 tAEVG8cC.net
>>62
ほーCopyってCloneの実装によらずmemcpy相当の結果になるのか
自動的に.clone()が差し挟まれる感じかと思ってた

79:デフォルトの名無しさん
22/05/17 07:41:41.18 1GDSnWAB.net
>>78
俺も同じくCopyは自動的にclone()されると思ってた
そう思ってた理由はClone実装せずにCopy実装するとエラーとなるため
そこで実験
#[derive(Debug,Copy)]
struct S { not_cloned: usize, cloned: usize }
impl Clone for S {
fn clone(&self) -> Self {
S { not_cloned: self.not_cloned / 3, cloned: self.cloned }
}
}
fn main() {
let s0 = S { not_cloned: 123, cloned: 456 };
let s1 = s0.clone();
let s2 = s0; // copy
println!("Cloned: {s1:?}");
println!("Copied: {s2:?}");
}
結果
Cloned: S { not_cloned: 41, cloned: 456 }
Copied: S { not_cloned: 123, cloned: 456 }
別物になった…

80:デフォルトの名無しさん
22/05/17 10:53:02 GxF458pr.net
>>52
>>>49
>デタラメすぎ
>ムーブでビットパターンのコピーは発生しない
>ビットパターンのコピーが発生するのは引数の値渡し等であってムーブとは関係ない
>さらに引数の値渡しでのでビットパターンのコピーとCopyのコピーも全く異なる
>Copyのコピーはディープであって高コスト

このレス最強だな
一つ一つの文すべてが間違ってる
「デタラメすぎ」てw

81:デフォルトの名無しさん
22/05/17 14:50:42.61 94ESmIzZ.net
ガイジムーブ来てんね

82:デフォルトの名無しさん
22/05/17 21:03:27.69 VS5jQHYL.net
Copyはshallow copyだわな

83:デフォルトの名無しさん
22/05/17 22:07:44 LjbtS7tD.net
色々と正確な情報が出揃ったところで質問

まず前提として話を明白かつ簡単にするため、
ここでは!DropつまりCopy実装可能な型のみ対象、
そしてもしClone実装するならば*selfつまりCopy実装と同一、
CloneやCopyを実装するかどうかは任意、
小文字のcloneとcopyはそれぞれCloneやCopyを実装した時にそれらが使われることを意味するとする

このとき、次のどちらの主張が正しい?
A「copy/cloneはコストが生じるので、回避できるならば回避したほうが有利」
B「copy/cloneのコストはmoveと同じなので回避する必要はない」

84:デフォルトの名無しさん
22/05/17 22:30:37.28 VUKzLr9a.net
場合による。
たとえコピーであっても結局は内容が同じものであると看破すれば
実際にはコピーしないようなコードを生成するといったことは有りうる。
Rust は原理的にエイリアス解析がやりやすい言語だと思うし。
実行コスト的にどうかなんて考えずに所有権管理の側面からの妥当性で決めたほうがよい。
その上でどうしても実行コストを切り詰めないといけないようになったならその時に考えればいい。

85:デフォルトの名無しさん
22/05/17 22:33:27.98 5/60CrrJ.net
>>83
前提もまちがってるが
比較する対象がそもそも意味がない
もうちょっと勉強してから出直して

86:デフォルトの名無しさん
22/05/17 23:40:20.70 XaJZCLYj.net
>>83
>A「copy/cloneはコストが生じるので、回避できるならば回避したほうが有利」
何と比べてコストが生じると言ってるの?
回避した場合は何で代用するつもりなの?

87:デフォルトの名無しさん
22/05/17 23:43:19.03 nlEgMvZ6.net
考えてみたけどmove/copyが問題になるレベルの大きさの型をスタックに置いて扱ったことが無いな…
使うとすれば固定長配列のバッファ?
でもそんなものmove/copyするわけないし
やっぱり考える意味の無い二択だと思う

88:デフォルトの名無しさん
22/05/17 23:47:41.13 FqAlYuq2.net
>>86
回避する前と回避した後の比較だろう
回避したコードが書けたならばcopyの代用の必要はない

89:デフォルトの名無しさん
22/05/17 23:49:36.53 YviCLBk+.net
>>83
一般的にはAが正しい
ただし>>84が言うように無駄なコピーが消える場合もある
A「copy/cloneはコストが生じるので、回避できるならば回避したほうが有利になることがある」ならば正確
Bについては前半はある意味正しいとしても後半が間違い
>>85
批判や主張はその理由を伴わないと議論とならず意味がない

90:デフォルトの名無しさん
22/05/17 23:54:01.76 VUKzLr9a.net
>>89
> 批判や主張はその理由を伴わないと議論とならず意味がない
基本的にはそうだが、こっちが説明しても理解できるレベルに達してない場合にはどうせ議論にならんのでな。

91:デフォルトの名無しさん
22/05/17 23:55:13.39 tAEVG8cC.net
あっこの流れC++相談室で見たやつだ

92:デフォルトの名無しさん
22/05/18 00:07:06.58 P5Km+xQv.net
要は参照使えるなら使っとけって?
今更すぎませんか

93:デフォルトの名無しさん
22/05/18 00:30:37.66 DGffctwq.net
オナコードペタペタされてたほうがマシだったなこりゃ

94:デフォルトの名無しさん
22/05/18 00:45:17.78 opn2S8Zb.net
>>92
それもあるが、例えば多数のコピーが行われているコードに対して、回避できる分を見直し、少数のコピーで済むように改善できる場合もある
Copy実装せずに明示clone()した方が見つけやすいかもしれない

95:デフォルトの名無しさん
22/05/18 01:26:17.77 lxQ5l4ey.net
>>88
さすがに意味が分からないよ
値の受け渡しにcopyを使わないなら何が他の方法を使う必要があるでしょ

96:デフォルトの名無しさん
22/05/18 01:42:43.25 d5NnfCmB.net
一人だけ間違った思い込みをしてるのに
説明されても「俺は間違ってない、間違ってるのはお前ら」が続くだけだからな

97:デフォルトの名無しさん
22/05/18 01:46:16.75 6ezlEFaX.net
>>95
頭が硬すぎないか?
回避できる分を回避するだけだろ
回避できない分まで回避する、と思い込んてるのはYouのみ

98:デフォルトの名無しさん
22/05/18 01:51:55.82 Da/MVUm8.net
>>89
「○○はコストが生じるので、回避できるならば回避したほうが有利になることがある」
言葉の定義を明確にしないジェネリック文は
恣意的に常に真にも常に偽にもできる

99:デフォルトの名無しさん
22/05/18 02:06:14.30 UgigdTUo.net
>>90
無駄にプライド高いな
嫌われるぜ

100:デフォルトの名無しさん
22/05/18 07:08:20 bcZKOTNR.net
大きいフィールドを持つ型には、Copyは実装しないだろうし普通はCopy/Moveのコスト差を気にすることなくない?
どちらにすべきかボーダーが難しいことはありそうだけど

101:デフォルトの名無しさん
22/05/18 07:14:11 P5Km+xQv.net
>>94
データフローを見直して単純に消せるclone/copyは消せってことか?
それこそ今更すぎるわ
単純に消せないところまで消した後、さらにパフォーマンス改善するにはどうするかってことで、参照の話か?って聞いたんだけど

どこの誰とも知れないやつのフィボナッチのコードに対する指摘をされても知らねーよ
問題があって対策が分かってるなら自分で直すがいい

102:デフォルトの名無しさん
22/05/18 07:41:25.51 4GWzufxp.net
>>97
実行回数の話だったのかよww
まさかねw

103:デフォルトの名無しさん
22/05/18 07:56:39.00 HgdHe2aE.net
>>101
フィボナッチの件はBigIntなど非Copyも対象で今回の話は全く無関係だろ
そこを区別できていないのは相当ヤバいぞ

104:デフォルトの名無しさん
22/05/18 08:12:27.72 BE/QrV8J.net
流れからすると本当はジェネリックのフィボナッチにCopyを付けないほうが有利と主張したかったんじゃね?
でも後から回避できないことに気づいて苦しい言い訳を重ねてるだけと見た

105:デフォルトの名無しさん
22/05/18 08:21:27.45 6swlbHlO.net
>>85
根拠も示さず批判だけする一番アカン人間やな

106:デフォルトの名無しさん
22/05/18 08:33:04.08 6hDwlDoy.net
>>104
フィボナッチはCopyを回避できないものなの?

107:デフォルトの名無しさん
22/05/18 08:45:43.18 2HNq06l+.net
分からないなら分からないから教えてって言えばいいのに意地を張るからこうなる
構えば構うほど意味不明な発言が出てくる
真面目に議論したいならせめてIDコロコロ変えるのやめな

108:デフォルトの名無しさん
22/05/18 09:10:15.39 Gy2qdhBc.net
フィボナッチってこれだろ
f(0) = 0
f(1) = 1
f(n) = f(n - 1) + f(n - 2)
関数呼び出しに足し算に大量のコピーは避けられない

109:デフォルトの名無しさん
22/05/18 09:28:25.87 3vPi03ro.net
>>87
async関数やasyncブロックで生成されるFutureは結構大きくなることがあって、boxingした方が性能出るケースもある

110:デフォルトの名無しさん
22/05/18 10:05:07.09 jV65BxdQ.net
>>106
型制約からCopyを外すこことcopyを回避することは全く意味が違う
>>83の質問は明らかに後者
プリミティブも対象になるフィボナッチでcopyを回避するのは無理

111:デフォルトの名無しさん
22/05/18 10:20:40.09 AWXqkW+Q.net
>>110
型制約からCopyを外せばプリミティブと言えどもcopyされなくなる
具体的には個々のプリミティブ型へモノモーフィゼーゼーションされる前の段階でCopy実装していない型に対してのcopy発生エラーが生じる
フィボナッチでcopyを回避するのは可能

112:デフォルトの名無しさん
22/05/18 10:38:43.35 2JRtSvHV.net
複オジの主張まとめ(1)
37, 39, 44
=====
CopyやCloneを使っているから別問題だろう。
一般的にRustのプログラミングでは、
Copy(暗黙的な自動コピー)やClone(clone()による明示的な手動コピー)を使うと楽になるが、コストは高くなる。
そのため不要なclone()を見極めてそれを回避するプログラミングが出来るかどうか、というRustにおける根源的な話だろう。
もちろんCopyは最もコストが高い。
個々のコスト自体は通常clone()と同じだが、常に自動的にclone()が起きるため最もコストが高くなる。
Copyはコストが一番高いから出来る限り避けるべきだな
特にヒープを使うならCloneまでにしておくべき
可能ならばCloneも避けるべきだが

113:デフォルトの名無しさん
22/05/18 10:39:05.95 2JRtSvHV.net
複オジの主張まとめ(2)
50, 52, 57
=====
それは理解不足すぎるぜ
大文字のCopyはCopyトレイトを意味しCopyトレイトを実装するか否かの話だろ
moveは別方向の話であり比較対象にすらならない
比較するならば「Copy実装(必然的にClone)も実装」「Cloneのみ実装」「どちらも実装なし」の3つだな
デタラメすぎ
ムーブでビットパターンのコピーは発生しない
ビットパターンのコピーが発生するのは引数の値渡し等であってムーブとは関係ない
さらに引数の値渡しでのでビットパターンのコピーとCopyのコピーも全く異なる
Copyのコピーはディープであって高コスト
これだけCopyやCloneを理解していない連中が多い状況だと
>>30の質問に答えられるかどうかは最低限クリアすべきテストとして有用ではないか?
フィボナッチ自体はもちろんどうでもよい話だがCopyやCloneを避けるRustの基本ができるかどうかわかる点で

114:デフォルトの名無しさん
22/05/18 10:41:41.09 2JRtSvHV.net
複オジの一連の主張を読んでから>>83の複オジ質問を読むべし

115:デフォルトの名無しさん
22/05/18 10:44:21.46 Jso4/z1R.net
複おじに反応するやつも複おじ

116:デフォルトの名無しさん
22/05/18 10:52:26.71 j9G6SOiS.net
主張が毎回変わる
口調も毎回変わる
表記も毎回変わる
間違いなく多重人格者

117:デフォルトの名無しさん
22/05/18 10:55:48.57 TXrPyH7a.net
>>98
この文脈では○○にはなんでも当てはまるから意味がないよね
以下なら議論になる?
A「copy/cloneはmoveよりコストが生じるので、copyが必要な部分とそうでない部分で構造体を分離してでも出来るだけmoveを使用する」
B「copy/cloneのコストはmoveよりコストが生じるとは限らないので、一部でもcopyが必要な部分がある構造体は丸ごとcopyして構わない」

118:デフォルトの名無しさん
22/05/18 11:00:11.80 TXrPyH7a.net
>>116
そこまでいったらネット上では別人で良いだろ

119:デフォルトの名無しさん
22/05/18 11:05:55.27 f/6XNiB/.net
>>108
やってみた
fn main() {
for n in 0..100 {
let f = f(n);
println!("f({n}) = {f}");
}
}
fn f(n: i32) -> i32 {
match n {
0 => 0,
1 => 1,
n => f(n - 1) + f(n - 2),
}
}
このあたりから非常に重くなった
f(43) = 433494437
f(44) = 701408733
f(45) = 1134903170
f(46) = 1836311903
f(47) = -1323752223
f(48) = 512559680

120:デフォルトの名無しさん
22/05/18 11:24:29.81 Rx65yaNy.net
メモ化されてないんやから遅くなるのは当然
>>108は定義を示しただけちゃう?

121:デフォルトの名無しさん
22/05/18 11:25:30.07 Rx65yaNy.net
つかオーバーフローしとるな

122:デフォルトの名無しさん
22/05/18 11:29:30.10 e0i+LLok.net
>>119
そのコードだとcopyは何回くらい発生してるのだろう
0回?1回?2回?3回?たくさん?

123:デフォルトの名無しさん
22/05/18 12:13:31 QV9C5cPM.net
ぼくのかんがえたさいきょうのcountup<T>()をみんなバカにしたので
ぼくのかんがえたさいきょうのfibonacchi<T>()でやっつけようとしたら
わざをだすまえにボコボコにやられてしまいました
く、くやしいです!

124:デフォルトの名無しさん
22/05/18 13:41:52 mX15beFi.net
clone()が一個でコンパイル通ったからそのコードでのコピーは一回ではないか

use std::ops::{Add, Sub};
fn f<T>(n: T) -> T where T: Clone + PartialEq + TryFrom<usize> + Add<Output=T> + Sub<Output=T> {
let [zero, one, two] = [0, 1, 2].map(|n| T::try_from(n).ok().unwrap());
match n {
n if n == zero => zero,
n if n == one => one,
n => f(n.clone() - one) + f(n - two),
}
}

125:デフォルトの名無しさん
22/05/18 13:50:00 FQ8O/3lA.net
>>119
計算量はO(n), メモリ使用量は定数オーダーにできるのになんで定義どおり実装したの?

126:デフォルトの名無しさん
22/05/18 14:41:04.77 xTux5YG/.net
>>123
ぼくのかんがえたさいきょうのfizzbuzz<T>()もわすれないで

127:デフォルトの名無しさん
22/05/18 15:04:45.49 dI/aN4vs.net
>>125
そんな魔法はありません

128:デフォルトの名無しさん
22/05/18 16:48:40.40 pQAvghMm.net
>>127
え?

129:デフォルトの名無しさん
22/05/18 17:53:48.13 jsK0MVuh.net
Rust以前の問題じゃん
スレ違い

130:デフォルトの名無しさん
22/05/18 23:22:25.69 z2ufbs5N.net
>>124
そのclone()は子のf(n-1)とf(n-2)やそれらの子孫でも呼ばれるので1回ではなくO(n)より大きい
それをO(n)すなわちn回+定数回以下に抑えられるのかどうか
あるいはO(0)回すなわち定数回以下に抑えられるのかどうか

131:デフォルトの名無しさん
22/05/18 23:41:48.24 RLh6XGtQ.net
フィボナッチはu128を使ってもf(187)でオーバフローするからBigInt必須
clone()はできる限り少なくしないと厳しい

132:デフォルトの名無しさん
22/05/19 00:10:47.96 SnnzWk5R.net
どうでもいいから複おじはTRPL読み直してきてね

133:デフォルトの名無しさん
22/05/19 00:16:28.52 IEr5OW/T.net
>>120
メモ化したら速くなったけど
memoをこちらで用意して毎回渡していくのを避けられないのかな?
fn main() {
let mut memo: Vec<usize> = Vec::new();
for n in 0..100 {
let f = f(n, &mut memo);
println!("f({n}) = {f}");
}
}
fn f(n: usize, memo: &mut Vec<usize>) -> usize {
if let Some(result) = memo.get(n) {
*result
} else {
let result = match n {
0 => 0,
1 => 1,
n => f(n - 1, memo) + f(n - 2, memo),
};
memo.push(result);
result
}
}

134:デフォルトの名無しさん
22/05/19 00:24:17.53 d4KplWCH.net
メモ化する必要ある?
直前の2つだけ記録しておけば次の一項が計算できるんだから再帰にする必要ないよね

135:デフォルトの名無しさん
22/05/19 00:33:12.40 IEr5OW/T.net
>>134
具体的にどうすればよいてすか?

136:デフォルトの名無しさん
22/05/19 00:46:08.98 HY3grr6d.net
>>135
"rust fibonacci"でググるとよいです

137:デフォルトの名無しさん
22/05/19 01:21:23 f3pwm4rC.net
>>134
直前の2つだけ記録して再帰にしない方法ならば
おそらくこうする案だと思うが
>>133がO(n)で済んでいるのに対して
これは二重のforによりO(n^2)になっていてこれは悪手

fn main() {
for n in 0..100 {
let f = f(n);
println!("f({n}) = {f}");
}
}

fn f(n: usize) -> usize {
match n {
0 => 0,
1 => 1,
n => {
let mut prepre = 0;
let mut pre = 1;
for i in 2..n {
let tmp = pre;
pre += prepre;
prepre = tmp;
}
pre + prepre
},
}
}


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

712日前に更新/84 KB
担当:undef