X



C++ vs Rust
レス数が1000を超えています。これ以上書き込みはできません。
0004デフォルトの名無しさん垢版2021/04/24(土) 10:50:18.68ID:N1eYD/7j
C++: カミソリ
Rust: 安全カミソリ
0006デフォルトの名無しさん垢版2021/04/25(日) 11:37:52.88ID:vJWG11Gh
一概にどちらが優れているとは言えないことではあるが、
代入やコンストラクタが、moveとcopyのどちらになるかについて、Rustの
方が自動化が進んでいると思いがちだが、実際は、
C++は、関数の戻り値が構造体型/クラス型になっている場合に関しては
RVO(Return Value Optimization)が働き、右辺が
クラス名(実引数列)
の形式の一時オブジェクトである場合には、moveが選ばれるが、それ以外は、
概ねcopyになるので、ある意味では「自動選択」しているのに対し、
Rustでは、x = y と書いた場合、原則的には「デフォルトmove」の規則に
従い、copyしたい場合は、右辺をy.clone()と書くことになっていて、
「手動選択」を採用している。
C++は、どう書いた場合にmoveになり、どう書いた場合にcopyになるかを全て把握するのは
難しくて、C++の仕様が勉強不足だと勘違いや見落としが発生する可能性があるのに対し、
Rust方式は、moveとcopyのどちらになるかが明確なので混乱が少ないと言えるかも知れない。
つまり、このことに関しては、児童選択より手動選択の方が安心感があるかも知れない。
意見を求む。
0007デフォルトの名無しさん垢版2021/04/25(日) 11:57:11.84ID:Ef2Yns/P
Copy trait実装してたら暗黙的に実行されるわ。
とはいえc++のそれよりかは分かり易いけど。
0008デフォルトの名無しさん垢版2021/04/25(日) 13:18:15.15ID:rtrHqrCb
[C++]
xやfunc()の戻り値が CPerson というクラス型の場合、
10. x = y; // copy代入。yの中味はxにコピーされる。yのデータも保存。
11. x = std::move(y) // move代入。yのデータは破棄される。
12. x = func(a); // move代入または、RVOが働いてmove代入以上に速い動作になる。
          関数の戻り値だけは特別に処理されている。

[Rust]
(CPerson がCopy traitを実装して無い場合に限定)
20. x = y; // move。以後、y は使用できなくなる。これが故にデフォルトmoveと呼ばれる。
21. x = y.clone(); // copy。以後もyは使用できる。
22. x = func(a); // move。20.と同じ規則に従っているだけで関数の戻り値だから特別では無い。

C++の場合、12.で関数だけは特別処理されているのに対し、Rustの22では
関数でも特別処理されているわけではなく、20.のデフォルトmoveの原則に従っているだけ
のように見える。
C++の場合、11. では、std::move()で修飾すると、なぜか、10. で修飾しなかった場合
より、実行されるCPUの処理が「減る」。ソースコードで関数の様なものを
追加した方が追加しなかったときよりCPUの処理が減ってしまうのは、どことなく直感に
反する。
一方、Rustの21と20を比較すると、.clone()を書いた方が書かなかったときより、
実行されるCPUの処理が増えるので、直感的である。
この場合、.clone()を書いたことで「コピーするためにCPUの処理が追加された」という
直感に沿った感じになるから。
C++の場合、std::move()と書くと「std::move()という関数の様なものを書いたのに、
なぜか、CPUの処理が減る」という違和感を感じるようになる。
0009デフォルトの名無しさん垢版2021/04/25(日) 17:13:07.94ID:In1fvQYU
要はRustの代入ってmemcpyで、単純なmemcpyされると困るデータ(!Copy)の場合右辺がinvalidate(move)され使えなくなる
って理解がシンプルなのかな
0010デフォルトの名無しさん垢版2021/04/25(日) 18:00:12.34ID:S2tV53BX
>>9
x = y の時、
結果的にはほとんどmemcpy(&x,&y,サイズ)に近い動作になっているかもしれないな。
ただ、右辺yの構造体メンバの中にRc<T>のような複雑なものが入っている場合、
結果は単純コピーのようになったとしても、コンパイラはもっと丁寧に処理
しているのではなかろうか。
0011デフォルトの名無しさん垢版2021/04/26(月) 01:44:08.26ID:+85I2LX6
>>10
move は memcpy だよ
Rc も実体はヒープへのポインタだから memcpy で問題ない
memcpy してはいけない例としては async fn みたいな自己参照構造体などがあるけど
Pin をうまく使うことで変な状態にならないようにしている
0012デフォルトの名無しさん垢版2021/04/26(月) 17:23:54.42ID:92SW7900
c++に批判的な姿勢で知られるlinusがなぜrustにはwelcomeな態度取ってるのかが理解できない
rustだってメモリ安全性がなければc++みたいなもんだろ
0014デフォルトの名無しさん垢版2021/04/26(月) 17:29:26.57ID:92SW7900
>>13
貶すまではいってないじゃん
0015デフォルトの名無しさん垢版2021/04/26(月) 18:48:21.42ID:pZ6mft9e
あわしろ氏もRustは凄いって言ってましたね。
C++をあまり好きじゃないところも同じ。
0017デフォルトの名無しさん垢版2021/04/26(月) 20:27:04.95ID:92SW7900
>>16
むしをrust側に対して例外処理の方法をカーネル内での往来の方法に変更してくれって促しているように見えるんだけど
導入したがってるやんけ
0019デフォルトの名無しさん垢版2021/04/26(月) 21:27:22.23ID:92SW7900
>>18
続きで懐疑的な立場取ってんのlinusじゃなくね?
0020デフォルトの名無しさん垢版2021/04/26(月) 22:53:32.32ID:cN+lbm0F
>>19
話の流れは大体予想できてただろうなという受け答えだろ。
んでもって実際、発案者自らmoonshot言うとるわ。
少しは内容を読んでくれ、なんで一から十まで説明しなきゃならんのか。
0021デフォルトの名無しさん垢版2021/04/26(月) 23:32:00.78ID:92SW7900
>>20
じゃあレスすんなよカス
0023デフォルトの名無しさん垢版2021/04/27(火) 00:14:36.96ID:H90KgUtd
>>20
moonshotって言ってるの割り込みコンテキストでallocator呼び出すことをコンパイル時にチェックできるようにしたいという話では
現実的には関数ごとにどのコンテキストで呼び出せるものなのかタグ付けしてるとかなんとか
綺麗じゃないけど、まあ動くわなという解決策

つまみ食いしかしてないから読み違えてるかも知れないけど
これをもってlinuxカーネルにrust取り込むのを否定するような話ではないようにみえた

他にもmoonshotって言ってる箇所ある?
0025デフォルトの名無しさん垢版2021/04/27(火) 08:00:23.09ID:/+bIFNU8
>>23
あのね。。書けばそうなるってものじゃなくてそれを実装しなきゃならんのよ。。
コンパイラにそういったコンテクストを判断させるのがめちゃくちゃ難しいっていってるでしょ?
なんでそんなに読み取れないの?
0026デフォルトの名無しさん垢版2021/04/27(火) 15:37:12.22ID:Nn42Sot0
>>25
当面はdoc commentにannotation書いて済ませておくって言ってるやん
何はともあれ大局的にはrustをlinux kernelに取り込む方向へ進んでいくことには間違いない
0027デフォルトの名無しさん垢版2021/04/27(火) 16:10:45.63ID:/+bIFNU8
>>26
だからそのコードじゃpanic捉えきれねーからカーネルに入れるわけねーだろって
言ってんじゃん。。何読んでんだよ。
0029デフォルトの名無しさん垢版2021/04/27(火) 20:32:29.92ID:/+bIFNU8
半年も経たなくてももうわかってるっつーの。。だからちゃんと英語の勉強しましょうね。
0030デフォルトの名無しさん垢版2021/04/28(水) 03:52:50.81ID:v8E9sca8
C++で、n要素のint型の生配列を確保するには、
int *pBuf = new int [n];
だけど、Rustの
let a:Box<i32> = Box::new<x>;
値が x である 32BIT 整数を Heap に 1 つ確保する、という意味だよね?
Heapに n 要素の i32 型の配列を確保したい場合、
let a:Vec<i32> = vec![0; n];
かな?
0031デフォルトの名無しさん垢版2021/04/28(水) 03:55:12.80ID:v8E9sca8
>>30
あ、
let a:Box<i32> = Box::new<x>;
ではなく、
let a:Box<i32> = Box::new(x);
let a:Box<i32> = Box<i32>::new(x);
let a = Box::new(x);
let a = Box<i32>::new(x);
かな。
0032デフォルトの名無しさん垢版2021/04/28(水) 04:01:18.27ID:v8E9sca8
>>31
確保した領域の中身を書き換えたい場合は「mut」を付ける必要があり、
値が x である 32BIT 整数を Heap に 1 つ確保するのは:
let mut a:Box<i32> = Box::new(x);
let mut a:Box<i32> = Box<i32>::new(x);
let mut a = Box::new(x);
let mut a = Box<i32>::new(x);
のどれかの書き方で、Heapに n 要素の i32 型の配列を確保するのが、
let mut a:Vec<i32> = vec![0; n];
let mut a = vec![0; n];
のどちらかの書き方かな?
0035デフォルトの名無しさん垢版2021/04/28(水) 15:21:28.78ID:jQpDsyge
[0; n]
って、n 要素のi32配列を確保して0で初期化するという意味らしいけど、
nは実行時に決まらないような変数も指定できるの?
0037デフォルトの名無しさん垢版2021/08/31(火) 15:22:27.39ID:8qO1h2Cp
246 デフォルトの名無しさん sage 2021/08/31(火) 14:25:42.76 ID:SlncBcTV
>>244
ポインタは適切に使えばデータ構造やアルゴリズム自体が根本的に変えることが
できるので使わない時と比べて計算オーダー自体が劇的に変化することがあり、
プラシーボではない。
Rustはその点でC/C++に勝てない事がある。

247 デフォルトの名無しさん sage 2021/08/31(火) 14:28:10.16 ID:SlncBcTV
例えば、動的配列であるところのVectorはポインタでアクセスしても余り
効率は良くならないが、LinkedListは構造的にポインタで連結されており、
首尾一貫して添え字アクセスを使わずに必ずポインタでノードを識別する
ようにすれば、Vectorに比べて劇的に効率アップできることがある。
それはRustではほぼ不可能。ベンチマークはこの点が反映されてない。
0039デフォルトの名無しさん垢版2021/08/31(火) 17:18:36.26ID:SlncBcTV
>>38
同じ動作をしてもVectorだとO(N)なのに、LinkedListだとO(1)になるものがある。
これだけでも実験してみなくてもNが大きくなった時に明らかに速度が
違うことはコンピュータ科学では常識。
例えば、コロナの感染者数は、O(exp(aN))になるので、どんだけ頑張っても、
Nが十分大きい時にはO(N^b)が上回ることは出来ない。
0040デフォルトの名無しさん垢版2021/08/31(火) 18:26:05.32ID:8qO1h2Cp
まだstable入りはしてないけどlinked_list::{Cursor, CursorMut}っていうのがあるね
そのベンチマークでは使ってる?
0043デフォルトの名無しさん垢版2021/08/31(火) 21:21:08.46ID:KWeLtswn
>>39
参照局所性の問題もあるから計算量の理論通りにはいかない場合もあるけど、ちゃんと性能測定してデータ構造選定した?
0044デフォルトの名無しさん垢版2021/08/31(火) 21:26:21.55ID:KWeLtswn
あとRustではほぼ不可能の意味が分からない
Rust にはポインタがあるから C や C++ のデータ構造はほぼ実現可能なのでは
0047デフォルトの名無しさん垢版2021/08/31(火) 23:58:27.88ID:SlncBcTV
>>42
ところが、Rustでは借用規則のせいで上手く行かない。
めんどくさいので自分で気づく人だけが理解してくれればいいので、
俺はこれ以上説明しない。
理解できない人は、親切な人が説明してくれるのを待て。
0049デフォルトの名無しさん垢版2021/09/01(水) 00:55:38.60ID:MtyAaHfZ
>>47
それはあなたが無知なだけだ
Rustはメモリ安全性を保証する
一方でRustの標準ライブラリではunsafeが多数使われているがこれはメモリ安全性を保証できる操作を効率よく実装するためにある
つまり論理的にメモリ安全性を保証できるならばunsafeを用いてもそれをライブラリやモジュールに閉じ込めることができる
もちろん自作でもこれは同様である
新たな型も当然作ることが可能
標準ライブラリで提供されているリンクドリスト型や双方向リスト型はそのようにして作られている
つまり効率をも落とさない
0052デフォルトの名無しさん垢版2021/09/03(金) 08:12:39.26ID:t+NhPRD1
>>49
ガイジ
0054デフォルトの名無しさん垢版2021/09/07(火) 23:30:30.79ID:W5eU3b0C
>>53 裏方のunsafeなコード(≠危険なコード)を安全に利用してプログラムを書けるのがRustだと思う
また、その裏方のunsafeなコードをRustで書く意味はRustから扱いやすいこと、Rustプログラマーが慣れたRustの文法で書けることがあると思う
0057デフォルトの名無しさん垢版2021/09/08(水) 09:53:24.22ID:8gtworgR
>>55 そうか、まぁ一個人の感想ぐらいに受け取ってくれ
0058デフォルトの名無しさん垢版2021/09/09(木) 16:53:30.53ID:lJRSMQ7p
なんだかんだ言ってまだまだC++だな
0060デフォルトの名無しさん垢版2021/09/09(木) 18:17:29.61ID:18O2MBOf
>>56
Rustはunsafeを局所的に安全に閉じ込めることができます
例えばVec<T>型はその各メソッド実装においてunsafeを用いています
これも『Rustがunsafeを局所的に安全に閉じ込めることができる』具体的な実例です

>>58
C++よりもRustの方が優れています
0063デフォルトの名無しさん垢版2021/09/10(金) 09:26:50.69ID:XIGB6bHM
数学的に間違いの意味がようわからんが、
unsafeブロック内あるいは関数内でSAFETYが守られるようにしないと安全に閉じ込めることができないって意味??
0064デフォルトの名無しさん垢版2021/09/10(金) 09:28:15.95ID:KDfyX1FH
Vec<T> が unsafe を使って安全なインターフェースを提供してることへの反論を示してくれ
0065デフォルトの名無しさん垢版2021/09/10(金) 11:00:27.70ID:4cVpX4oe
>>63
そうでなくて、unsafeブロックで閉じ込めようとしても、閉じ込め切れなくて、
O(x)で表される計算時間が、C言語とは同じでは絶対に不可能な場合があるんだ。
Rustのsafeモードでは、コンテナの中のノードに対して書き込み参照と読み込み参照
を持つことが借用規則によって禁じられていることが原因。
C言語ではそれが当たり前に出来るからとても効率の良いプログラムが可能だが
Rustでは、unsafeの外側ではそれが出来ないから不可能だ。
アプリレベルでそれが出来ないから。
これで納得できない人は数学の才能が無い。
俺は数学の天才。
0066デフォルトの名無しさん垢版2021/09/10(金) 11:05:19.78ID:4cVpX4oe
>>65
数学の才能が無い人のためにもう少し詳しく書いてやろう。
・Rustのsafeモードでは、LinkedListの中の複数のノードに対して、
 読み込み参照と書き込み参照を一度自動時には持てない。
 持つと borrow cheker がコンパイル時にエラーを出してしまう。
・C言語ではそれが当たり前に出来る。
・アプリレベルで1つのLinkedListに対して複数の読み込み参照と
 書き込み参照を同時に記録し続けることで、やっと、挿入や削除が
 O(1)になる。index 値で保持すると O(N)になってしまうから、
 vector と同じ速度オーダーしか出ない(つまり、LinkedList本来の性能
 が全く出せない。)
・結果、Rustは、Cより遅いプログラムしか出来ない。その遅さは、データが
 多いとき、C言語に比べて1万倍でも100万倍でも遅くなる。
0068デフォルトの名無しさん垢版2021/09/10(金) 11:30:01.67ID:4cVpX4oe
>>67
RustとCの知識と、東大数学が簡単に解けるような数学の才能をすべてもっている人
に聴いてみろ。
0069デフォルトの名無しさん垢版2021/09/10(金) 11:36:42.07ID:4cVpX4oe
>>68
本当は次のような知識も必要:
・リンクドリストの構造。
・リンクドリストの挿入、削除などの計算オーダーO(x)。
・計算オーダーの記号O(x)の意味。ビッグオー。ランダウの記号。
 東大、京大の学部レベルの解析学(微分積分学)の本を見よ。
・index 値 = 基本は配列の添え字。0から割り振られた連番。
 リンクドリストでは本来使わないが、Rustではノードの場所を覚えておくために
 使わざると得ない。その場合、リンクドリストの先頭のノードを 0 番とし、
 次のノードを 1, その次のノードを 2 のように表す。
 しかしそうすると、リンクドリスとの M 番目の場所の参照を取得するのに
 O(M)の時間が掛かってしまい、リンクドリストの効率の良さが台無しになってしまう。
・このことから、リンクドリストが遅いという誤解を生む状況になってしまっている。
0071デフォルトの名無しさん垢版2021/09/10(金) 11:39:59.60ID:4cVpX4oe
>>70
高校生が灯台に入学するときに受ける東大の数学の試験のことだよ。
それが簡単に解けるくらいのやつに聞いてみろって事だ。
しかし、受験テクニックやパターン学習によって解ける様になったやつはダメだ。
0073デフォルトの名無しさん垢版2021/09/10(金) 11:52:48.63ID:2Djs9W2b
>>72
i 番目の要素というと不正確か
ポインタの代わりに Arena 内での index を使うことで LinkedList のノードを O(1) で参照することができる
0074デフォルトの名無しさん垢版2021/09/10(金) 11:53:08.66ID:FsmeH+FF
https://play.rust-lang.org/?version=nightly&;mode=debug&edition=2018&gist=bc6e823f6a44e442aabd4d4882d3eb5a

Repeated 1 time(s), duration = 2.531µs
Repeated 10 time(s), duration = 4.661µs
Repeated 100 time(s), duration = 29.449µs
Repeated 1000 time(s), duration = 256.555µs
Repeated 10000 time(s), duration = 1.800129ms
Repeated 20000 time(s), duration = 3.273489ms
Repeated 50000 time(s), duration = 8.345219ms
Repeated 100000 time(s), duration = 16.454731ms
Repeated 200000 time(s), duration = 32.911471ms
Repeated 500000 time(s), duration = 83.993118ms
Repeated 1000000 time(s), duration = 166.193956ms

結構実行毎にゆれる感じはあるけど、おおむねO(1)じゃないですかね
0075デフォルトの名無しさん垢版2021/09/10(金) 12:09:20.46ID:4cVpX4oe
>>74
アホですか?

>>73
Arenaを使った時点で裸のリンクリストじゃ無いし、時間は、O(x)が同じでも
オーバーヘッドが発生する。また、無駄なメモリー領域も食う。
0079デフォルトの名無しさん垢版2021/09/10(金) 12:18:20.87ID:FsmeH+FF
>>75
はい、私はアホで数学の才能が無いので数学の天才様の問題意識が分かりません
VecならO(n)になる先頭への挿入がO(1)でできることを示したつもりでしたが見当違いでしたでしょうか
0080デフォルトの名無しさん垢版2021/09/10(金) 12:27:50.85ID:4cVpX4oe
>>79
push_front()使ってるから先頭へ挿入してるだけじゃないか。
Cのリンクリストは、どんな非負整数 M に対して、M番目に挿入しても
MにもNにも依存しない定数時間で挿入できる。
それがRustに欠けている。
0081デフォルトの名無しさん垢版2021/09/10(金) 12:28:54.60ID:2Djs9W2b
>>75
そのオーバーヘッドは実用上問題になりますか?
例えばmallocの実装もarenaを使っていますが問題はないのですか?
そもそも計算量の議論をしていたのはあなたなのになぜ論点をずらすのですか?
0083デフォルトの名無しさん垢版2021/09/10(金) 12:41:50.91ID:4cVpX4oe
>>82
「M番目」のMをそのまま「通し番号」で表しているならその通りだ、たとえC
であっても。
しかし、Cでは、通し番号ではなくポインタで表現することで1クロックで
辿り付けるので O(1)。
0084デフォルトの名無しさん垢版2021/09/10(金) 12:42:38.21ID:XIGB6bHM
>>65が何言ってるのか1行たりとも理解できなくて日本語の見た目した何かにしか見えないんだけど、
なんで話が進んでるの・・・
0086デフォルトの名無しさん垢版2021/09/10(金) 13:34:07.88ID:4cVpX4oe
>>85
「M番目に挿入」するが、それをMという数値で識別するとは書いてない。
数学とはそういうものだ。
ポインタ p で表現する場合でも、p が M 番目のノードを指していることがある。
その場合は、M番目に挿入と表現される。
そう表現しないと、O(x)記号で表現しにくいからだ。
0087デフォルトの名無しさん垢版2021/09/10(金) 13:35:00.70ID:FsmeH+FF
>>83
それと同じことをRustではポインタの代わりにCursorMutを使って実現できる、という認識ですが
CursorMutには何が欠けていますか?
0088デフォルトの名無しさん垢版2021/09/10(金) 13:35:29.31ID:4cVpX4oe
数学での言葉の表現と日常の言葉の表現は異なる。
「M番目に挿入」することと、そのノードを、index = M - 1 で表すこととは
別の話だ。
0089デフォルトの名無しさん垢版2021/09/10(金) 13:47:35.86ID:4cVpX4oe
>>87
同じノードを複数のCursor/CursorMutが参照している場合、1つの参照経由
でノードを削除した場合、別の参照がダングリング参照になるのを0コストで
防ぐ方法は無いはずだ。
静的解析が不可能で、時間や記憶域に何らかのオーバヘッドが必要となるはず。
0090デフォルトの名無しさん垢版2021/09/10(金) 14:16:45.03ID:4cVpX4oe
さらに、1つの LinkedListに対して、同時に2個以上の CursorMut を作ることは
出来ないはず。
0091デフォルトの名無しさん垢版2021/09/10(金) 14:18:55.00ID:iOAXb/4V
Cでリンクドリストの途中を直接ポインタで持っていると速いが
その途中が削除された場合にそのポインタは危険なポインタとなる
つまりCで記述しても何らかのコストをかけなければ安全に出来ない
つまりこの問題はどの言語であろうがコストゼロにすることは不可能
0092デフォルトの名無しさん垢版2021/09/10(金) 15:27:02.65ID:I2sJLr90
>>91
いや、数学が得意な人は頭がいいので、それでも至って安全なプログラムが書けるし、
今ままでも書いてきた。
Rustは数学の得意な人間には遥かに及ばない。
0093デフォルトの名無しさん垢版2021/09/10(金) 15:44:47.65ID:EyQ85oMr
すげぇバカ
0096デフォルトの名無しさん垢版2021/09/10(金) 17:11:54.58ID:lpjuAWj9
どんな非負整数Mに対して
と自分で書いている
当然与える情報はMである

各Mに対応するポインタを保持するなら
挿入時にそのテーブルを更新しなきゃならないから
O(1)では出来ない
0097デフォルトの名無しさん垢版2021/09/10(金) 17:38:39.28ID:dS7angqs
>>96
Mを与える情報とは書いてない。
Mというものを使わないと、LinkedListとVectorで共通した議論が出来なく
なるから書いてるだけ。数学では良く使う論法。
つまり、Mは、議論の中で場所を特定するために用いているだけで、
プログラム中で用いているとは言ってない。
0098デフォルトの名無しさん垢版2021/09/10(金) 17:41:20.99ID:dS7angqs
例えば、コンテナに100個のノードが入っていたとする。
コンテナは、LinkedListやVectorなどどんなアルゴリズムを使っているかは何でも良い。
で、「5番目の場所にノードを追加する」という言葉は、LinkedListにも使えるが、
その場合、プログラム中では5という数値で識別せず使わず、ポインタで識別する
のが C言語での常識。
でも、「5番目の場所に追加する」という言葉は使ってよい事になっている。
0099デフォルトの名無しさん垢版2021/09/10(金) 17:43:19.62ID:iOAXb/4V
>>96
その人は数学が得意と言いながらそこすら理解できていない人だからね
Cでもプログラミングしたことあるならすぐわかることだからプログラミング経験も乏しいと推測される
つまりRustを叩きたいだけの人が暴れているだけの構図
0100デフォルトの名無しさん垢版2021/09/10(金) 17:48:47.41ID:dS7angqs
>>99
理解してる。
お前らが、M番目のノードを数値Mでプログラムでも辿ると勘違いしている
抽象化が理解できない馬鹿だからそう思ってるだけ。
俺は抽象化が得意だから、M番目のノードをポインタで識別すると
考える。お前らは、Mとpを脳内で橋渡しできないだけ。
0101デフォルトの名無しさん垢版2021/09/10(金) 17:49:37.61ID:dS7angqs
数学的才能の無い人とは話が合わない。
知能に差が大きすぎる人達とは話が合わない。
0103デフォルトの名無しさん垢版2021/09/10(金) 18:15:44.49ID:ae9TKcqK
>>100
君は数学が不得意だな
入力Mに対してM番目を得る関数のコスト(リソースコストなど含む)を考えればいいだけなのにそれができない
抽象的に考えるのが苦手なら具体的な関数のプログラムを考えてもよい
Rustを叩きたいだけだとしてもC言語のプログラミングくらいはできるんだろ?
君の主張が間違っていて実現不可能なことがすぐわかる
そして示せなければ君の完全敗北確定だ
0104デフォルトの名無しさん垢版2021/09/10(金) 18:22:19.32ID:uQqwzIiF
>>98
完全に屁理屈
それならわざわざ「どんな非負整数Mに対しても」なんて言う必要は全く無い
任意のノード、任意の箇所
ならまだそういう可能性もある

たまたまMに対応するポインタがキャッシュされてた場合の計算量を言っても何の意味も無い

ちなみに数学的能力はお前よりあると思うよ
実績で勝負するなら付き合う
0105デフォルトの名無しさん垢版2021/09/10(金) 18:33:25.73ID:HO5HNd+Q
>>65
> 俺は数学の天才。

これみて釣りと判断してるけどマジに受け取ってる人もいるのかな?
議論を続けるなら数学うんぬんの要素を抜きつつアクセス効率だけ語ってほすい
0107デフォルトの名無しさん垢版2021/09/10(金) 22:29:30.98ID:S72cPfGI
自分は数学できないからできる人の相場感覚は分からないが、数学の天才って◯◯予想を証明したとか、定理に自分の名前が付いているとか、そういうレベルの人のことじゃない? 東大数学程度で数学の天才を名乗られても……。
0108デフォルトの名無しさん垢版2021/09/10(金) 23:03:29.47ID:G/i8H+xj
> 高校生が灯台に入学するときに受ける東大の数学の試験のことだよ。

高校数学でここまでイキれるのはもはや才能だと思うわ
数学の天才っていうのは数学の研究してて教科書書いてるような
著名な人をまわりの人が「他称」するときの話で
高校数学の成績で「自称」しちゃうってのは別の才能w
0109デフォルトの名無しさん垢版2021/09/10(金) 23:04:20.56ID:uQqwzIiF
東大でやる数学じゃなくて入試でしょ?
つまり高校レベル
こんなのを東大の数学と言うな
0110デフォルトの名無しさん垢版2021/09/11(土) 01:22:42.58ID:Q/hQI3Xf
知ってる一番難しい数学がそれだったんでしょ
つっこんであげないのが優しさでは
0111デフォルトの名無しさん垢版2021/09/11(土) 01:40:01.24ID:PRM8i6LA
>>80
C言語でも他の言語でもそのようなことは実現不可能です
いくらRustを叩きたいとはいえ主張が滅茶苦茶になっていますよ
0113デフォルトの名無しさん垢版2021/09/11(土) 11:20:17.45ID:PFLibieQ
実際連結リストのノードに対する参照を保持しておくってどういうユースケースで現れるんだろうか
0114デフォルトの名無しさん垢版2021/09/11(土) 11:40:09.41ID:tSun79KI
掲示板で算数自慢するときに使う
0115デフォルトの名無しさん垢版2021/09/11(土) 11:42:49.15ID:kQXQH3+b
>>113
例:

1. テキストエディタで、10万行のファイルを読み込み、その先頭に
1000行のテキストを挿入するときの速度向上。

2. 言語を自作する時、マクロ展開の時のトークン列へのトークンの挿入
0116デフォルトの名無しさん垢版2021/09/11(土) 16:43:18.56ID:zUj2TAiQ
>>115
それはどちらの使用例なのかハッキリしてほしいです。
配列にN番目への参照を格納する例として挙げているのか、
そうではなくリンクリストを用いる例として挙げているのか、
どちらですか?
0117デフォルトの名無しさん垢版2021/09/11(土) 23:33:36.29ID:EO9owr6G
>>112
0118デフォルトの名無しさん垢版2021/09/12(日) 00:21:25.00ID:CFIv5O+a
相手をバカと貶めることで何もしなくても自分わ相対的に高めることができるという高等な議論テクだ
さすが高学歴
0119デフォルトの名無しさん垢版2021/09/12(日) 02:54:54.78ID:x/1IPUIX
>>115
1.ってバッファを1個のLinkedListとして持っておいて、カーソルの位置をノードへの&mutで持っておきたいって発想だよね
それよか2個のLinkedListに「カーソル以前の内容」「カーソル以降の内容」を最初から分けて持っておいて、
必要に応じて前者の末尾または後者の先頭を操作するという風にすれば、常に&mut LinkedListつかまれることもなくて都合良いのでは?

workaroundでしかないという批判は認めよう
0120デフォルトの名無しさん垢版2021/09/17(金) 13:36:25.88ID:9sB/yeOV
任意のM番目に要素を挿入する時間計算量がO(1)の線形リストができないと入院中の妹が苦しむんだわ…
0122デフォルトの名無しさん垢版2021/10/05(火) 15:44:11.57ID:+1Hntkr6
素人だからよく分からんけど、実務やってる人からCppだとvoid**とか出てきて難しすぎて狂うって話は聞いたことあるけどラッパークラスを作って分かりやすいメソッドつくればいいんじゃないの
0123デフォルトの名無しさん垢版2021/10/05(火) 18:47:14.74ID:JbR3YU6O
void**のどこが難しいのかさっぱり
0125デフォルトの名無しさん垢版2021/10/24(日) 13:55:43.29ID:eQqSgpa/
任意の言語ができる操作が任意の言語ではできないとほざくやつが数学ができるとかネタか糖質だろう...
チューニングマシンの存在を真っ向から否定したいならここではなく学会で論文を出そうね
0130デフォルトの名無しさん垢版2021/10/24(日) 20:55:50.68ID:IF6Ria+p
rustの所有権は所謂、線形型
普通に理論として確立している
数学できるくんの主張は線形型によってチューニングマシンの計算複雑性が変化するってことだろう
証明できたらチューニング賞ものだろう
何十年ぶりじゃないか?記述計算量に新しい概念が導入されるのは
0131デフォルトの名無しさん垢版2021/10/24(日) 22:07:03.33ID:+peTc5KU
rustの所有権や借用や、コンパイルが通らずにいらいらきますが、慣れればスラスラというか、ストレスなく書けるようになるのかな
0132デフォルトの名無しさん垢版2021/10/24(日) 22:10:42.59ID:+peTc5KU
日本語がおかしいですが、
所有権や借用が、やりたいことをストレスなく書けるようになる気がしなくて…
0133デフォルトの名無しさん垢版2021/10/24(日) 22:29:10.11ID:HVo+cqVA
慣れみたいなものはあると思う
コンパイル通るようコード直すことを繰り返す内に最初からコンパイル通すことができるようになるかと
0134デフォルトの名無しさん垢版2021/10/24(日) 22:41:32.45ID:+peTc5KU
>>133
ありがとうございます
やはり繰り返しと慣れですね…

もう少し分かるまで粘ってみます
取り急ぎお礼まで
0136デフォルトの名無しさん垢版2021/10/25(月) 20:25:16.68ID:cubP7NbG
>>135
ご利益の大小はソフトウェアの種類によって変わるだろうね
OSやブラウザのようなメモリアクセス違反が即致命的な脆弱性に繋がり得る、かつ、巨大でバグを取り除ききるのが難しいソフトではご利益大きい
逆に多少バギーでも困らないソフトならただ煩わしいだけというのは正しいかも
とはいえ慣れればコンパイルが通るようにコードを書くのは多くの場合難しくないので、個人的にはカジュアルユースでもコストよりメリットが多いように感じる
0137デフォルトの名無しさん垢版2021/10/26(火) 18:03:05.91ID:KgmW7hJW
>>136
め早口
0138デフォルトの名無しさん垢版2021/10/26(火) 20:06:45.12ID:OracOvFU
>>131
「最後に消費するのは誰か?」を明確にするだけでよくて
その人以外に渡す時は借用してもらうだけだよね
あとはmut借用だけ一時的独占でルールおしまい
0139デフォルトの名無しさん垢版2021/10/26(火) 22:54:07.10ID:XkR6Nv6d
>>138
コメントありがとうございます
いまはまだおっしゃることにピンとこないのですが、「最終消費者は誰か」は常にこころに留めて進めてみます
まだサンプルコードを写経している段階なので、具体的なテーマを見つけて苦労してみます

>>135 さんもありがとうございます
ホント、小煩い姑状態です
親父の小言は後に効く、といいますが…

haskellでいう型クラスや、代数データ型、パターンマッチなど魅力的な機能があり、はやく馴染みたいです…
0140デフォルトの名無しさん垢版2021/10/26(火) 23:17:46.13ID:zVG+0sad
>>29
まさに半年経ってようやくカーネルにアロケーター導入されたわけだが
完璧に君の負けだよね
お疲れ様です
0143デフォルトの名無しさん垢版2021/10/27(水) 09:23:36.95ID:q+lzbSiO
あちゃちゃwそれ別のapiじゃんw
お馬鹿さんだからメーリス追えないんだねww
0144デフォルトの名無しさん垢版2021/10/27(水) 09:29:13.91ID:zfYVqfDQ
話追えるようになってから来てくださいね🤗
0145デフォルトの名無しさん垢版2021/10/27(水) 09:30:10.86ID:zfYVqfDQ
頭悪いのどっちかな
0148デフォルトの名無しさん垢版2021/10/27(水) 16:58:29.94ID:Ru0zcXw7
顔真っ赤っかで草w
悔しいねえw
0149デフォルトの名無しさん垢版2021/10/27(水) 16:59:43.91ID:3BkIbLo2
>>146
頭悪いの君だよね?
0150デフォルトの名無しさん垢版2021/10/27(水) 18:36:52.66ID:zwnES/cK
あわしろ氏がLinuxをRustで書き直すプロジェクト始めなかったっけ。
0151デフォルトの名無しさん垢版2021/11/21(日) 11:28:03.98ID:aXP4f2By
どんなに簡単でも、できることに制限がある言語は流行らない、という経験法則がある。
Rustも使えるアルゴリズムに制限があるのだが。
例えば、C言語で使えていたアルゴリズムは、C++/Java/C#ではそのまま使える。
特にC++とC#には、Cから移行するときの制限が少ない。
ところがRustでは、これらのコードからはシンプルには移植できないものが存在
してしまう。
C#やJavaは速度を遅くする代わりに安全性と自由性の両方を確保できているが、
Rustは、速度は余り遅くならないが、自由性を犠牲にしている。
これは大問題となるだろう。
0155デフォルトの名無しさん垢版2021/11/21(日) 14:23:27.74ID:qwOTZsAN
>>153
unsafeの中だけに閉じ込めきれないのが問題。
例えば、C言語の場合、アセンブラにしか掛けないことは、アセンブラでコードを書いた
ものをCの関数にして、Cから呼び出すことが出来たので問題なかった。
ところがRustの場合、リンクリストをポインタや参照を使って高速に扱うことが
unsafeの中だけでは完結できないので無理。
結論的には、リンクリストをO(1)でアクセスすることがRustのsafeモードでは
完全に不可能といえる。たとえ unsafe モードを使っても、safeモードに
「しみ出してきて」駄目になる。
0156デフォルトの名無しさん垢版2021/11/21(日) 14:25:17.13ID:qwOTZsAN
Rustを使うなら、次のデータ構造をCのように「効率よく扱う」のは諦めるしかない:
・リンクリスト
・ツリー構造(バイナリツリーなども含む)
なんどもいうが、unsafeモードをいくら使っても言語の構造上、
無理なものは無理。
俺は数学の天才。最初から結論が分かる。
0157デフォルトの名無しさん垢版2021/11/21(日) 14:27:35.80ID:qwOTZsAN
何度も言おう。
Rustでリンクリストやツリー構造をO(1)でsafeモードからランダムアクセス
できないことは数学的に完全に証明できる。
そしてそれは、unsafeモードをいかに工夫して使っても無理。
無理なものは無理。これは絶対。
俺は数学の天才。
0158デフォルトの名無しさん垢版2021/11/21(日) 14:30:47.72ID:qwOTZsAN
[補足]
それが出来るんだったらもっと普及してるし、もっと真似されてる。
Rustのやり方では不可能だから普及できない。
0161デフォルトの名無しさん垢版2021/11/21(日) 19:24:03.14ID:a8amZ/lG
>>157
また嘘つきがRust叩きをしているのか

>リンクリストやツリー構造をO(1)でランダムアクセスできない

これは全てのプログラミング言語で不可能
もちろんC言語でも不可能
以前も皆に論破されて逃走したのにまた戻ってきたのか
0164デフォルトの名無しさん垢版2021/11/21(日) 19:49:09.49ID:/ddxrWFf
C/C++が速いのは、リンクリストのおかげだ。
Stroustrapも馬鹿だからリンクリストを理解できてない。
vectorだけでは人気アプリの速度は達成できてない。
0168デフォルトの名無しさん垢版2021/11/21(日) 20:53:48.92ID:ZPin+mWW
算数得意おじちゃんが生えてきたな
0170デフォルトの名無しさん垢版2021/11/22(月) 00:50:22.67ID:saDsX792
>>168
余りにも馬鹿すぎるから、発言者の背景を示すしかなかった。
IQの違いが大きすぎると話が通じないと言われるが、まさに
このスレがそうで、ちゃんと言わないと、正しいことを言ってる
人が馬鹿にされるから。
0171デフォルトの名無しさん垢版2021/11/22(月) 01:02:53.27ID:saDsX792
>>166
・Cだとリンクリストやツリーの中のノードを識別するのに、通し番号ではなく
 ポインタが使われる。そのポインタは、関数内部にとどまらず、
 アプリ全体で大規模に保持され続け、ノードが必要になった場合、それを
 介してノードにアクセスする。だから、読み込みも書き込みも自由自在に
 行える。一つのツリーの中の有るノードを削除し、あるノードに子ノード
 を追加し、あるノードの直後に弟ノードを追加し、あるノードを読み取り、
 あるノードに書き込む、などを全く任意のタイミングで行える。
 繰り返しになるが、これらのポインタはある関数の内部だけで完結
 せずに、関数の外のグローバル変数にアプリの起動時から終了時まで
 恒久的に保持され、必要なタイミングで使用される。

・Rustではこのようなことが不可能。ツリーのノードを指す参照を、
 グローバル変数に複数保持して、書き込みと読み込みを自由自在に
 行うことが不可能だかっら。
0172デフォルトの名無しさん垢版2021/11/22(月) 01:07:59.95ID:saDsX792
>>171
[補足]
Cの方で説明したやり方は、C++/C/Javaでも可能。
JSやRuby、Pythonでも可能。
Rustだけが不可能。
つまり、多くの言語が出来る中でRustだけが出来ない。
その結果、数学的な意味での「一般的」には、TreeやLinkedListでまともな性能が出ない。
もちろん、特定のケースでは同等性能が出ることはあるが。
0174デフォルトの名無しさん垢版2021/11/22(月) 01:32:04.72ID:saDsX792
>>172
[補足2]
通し番号ではなく、ポインタでノードを識別することで、末尾以外のノードを
削除した時でも、識別番号の書き換えが不要であるメリットもある。
ポインタとはアドレスを保持する変数のことであるが、リンクリストや
ツリー構造の場合、途中のノードを削除しても、別のノードのアドレス
は全く変化しないので、削除したノード以外のポインタ値は全く変更されないので
書き換えも必要ないからである。

一方、初心者がやりがちなのは、リンクリストでも先頭のノードを0番にして、
それ以後のノードを1、2、3 という通し番号で識別しようとする方法。
これだと、5番のノードを削除した時、6番以後のノードは番号の付け替えが
必要になるのでものすごく効率が下がる。
また、k 番のノードをアクセスする際には、O(k)の時間が掛かってしまう。
本来、Cではノードを識別するのは、このような通し番号ではなく、
ポインタ(アドレス)で行うのが伝統であって、アルゴリズムの教科書でも
それが前提になっている。
それがいつからか、リンクリストでも通し番号で識別する流儀を誰かが持ち込み
初めて混乱が生じるようになった。
0176165垢版2021/11/22(月) 02:04:09.01ID:43z4eYfr
>>169,172
なるほど、そうなんだ
でも正直、なにを言ってるのかまだよくわからんから、ちょっとベンチマークを投稿して遅さを示してみてくれん?
Linked Listの実装なんてその投稿よりも圧倒的に短く書けるとおもうし、ちょっとやってみせておくれ
0177デフォルトの名無しさん垢版2021/11/22(月) 10:14:51.86ID:ejqG4gpN
pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T>
This is a nightly-only experimental API. (linked_list_cursors #58533)

CursorMutのStabilisedがまだ来てないことへの批判ってこと?
0178デフォルトの名無しさん垢版2021/11/22(月) 10:24:02.08ID:EEj8G+es
>>157
> Rustでリンクリストやツリー構造をO(1)でsafeモードからランダムアクセスできない

どんな言語で書いてもO(1)でランダムアクセスできないのでRustでも同様にO(1)でできないのは当たり前
一般的にランダムでkが与えられた時にリンクリストでk番目を得るにはO(n)かかる
C言語でもO(n)でありO(1)では不可能
0181デフォルトの名無しさん垢版2021/11/22(月) 11:50:19.99ID:EEj8G+es
>>179
君はプログラムを書いたことがないのかね?
どんな言語でもランダムでkが与えられた時にリンクリストでk番目を得るにはO(n)かかる
O(1)でできると主張するならば実行可能なソースコードを出しなさい
0182デフォルトの名無しさん垢版2021/11/22(月) 12:28:55.95ID:8vjqlXjx
説明足りてないな。
「過去に一度対象となるコンテンツのポインタを確認&記録している場合」じゃなきゃO(1)は無理だろ。
0184デフォルトの名無しさん垢版2021/11/22(月) 13:15:10.95ID:EEj8G+es
>>182
ランダムでkが与えられた時にリンクリストのk番目を常にO(1)で得るためには
全てのk番目の位置を別途ベクターで保持管理しないといけなくなる
そしてリンクリストで挿入削除が行われるたびにk番目がズレるから保持管理ベクターで毎回O(n)の移動が発生する
つまりどんな言語でもO(1)は絶対に不可能
0185デフォルトの名無しさん垢版2021/11/22(月) 17:14:17.10ID:HWCOZSD4
>>181
そう思うのは、ランダムアクセスの定義をあなたが誤解してるからだ。
確かに、リンクリストに置いて、何の情報も無く「k番目」のノードに
アクセスするにはO(k)の時間が掛かる。
しかし、そのアクセス方法は、ランダムアクセスする場合に必須ではない。
p1, p2, ..., p_a
というa個のポインタがあって、それをランダムに選び取ってアクセスする場合の
1つあたりに掛かる時間が、O(1)であれば、ランダムアクセスの時間はO(1)
だと言えるから。
連続アクセス以外は、全てランダムアクセスなんだ。
具体的には、最初から100個のノードのアドレスを、100個のポインタに記録していたとしよう。
そのポインタは、リンクリストの中の位置で見ると、連続して並んでいるわけではないとする。
そのポインタを順番に参照してリンクリストのノードをアクセスすれば、連続アクセスでは無いから、
ランダムアクセスに分類される。
もう一度言おう、連続的な位置では無いノードを複数個アクセスすればランダムアクセスだ。

IQが低い人は、こういうトンチのようなものに弱い。
だから、IQの高い人とIQの低い人では誤解が生じ、大変な結果となる。
0186デフォルトの名無しさん垢版2021/11/22(月) 17:17:59.19ID:HWCOZSD4
>>184
どうしてあなたは、2つの概念を切り分けられないんだ。
kを任意に与えられてk番目のノードをアクセスするには、確かにO(k)の
時間が掛かるが、ランダムアクセスは、最初からアドレスが分かっている
ノードをa個アクセスした場合の1つ当りのアクセスに掛かる時間でも
いいんだから、必ずしもO(k)ではなく、O(1)になる場合がある。
数学は精密な学問だから、場所をランダムにアクセスすることと、
毎回kという通し番号が与えられて毎回前から順番に辿ることとは
全く別の事象である。
ちなみに俺は、数学は毎回100点とっていたような数学マンだ。
0187デフォルトの名無しさん垢版2021/11/22(月) 17:18:11.48ID:EEj8G+es
>>185
ランダムでkが与えられた時にリンクリストのk番目を常にO(1)で得るためには
全てのk番目の位置を別途ベクターで保持管理しないといけなくなる
そしてリンクリストで挿入削除が行われるたびにk番目がズレるから保持管理ベクターで毎回O(n)を必要とする移動が発生する
つまりどんな言語でどんな手法でもO(1)は絶対に不可能
0188デフォルトの名無しさん垢版2021/11/22(月) 17:26:17.83ID:HWCOZSD4
IQが低い人向けに書いておこう。どうせ書いても理解できないかも知れないが。
リンクリストの中にx0〜x_{N-1}のN個のノードがあったとしよう。
ランダムアクセスの定義は、「連続アクセス以外の全てのアクセス方法」であるので、
以下のようになっている:
[連続アクセス]
x0,x1,x2,x3,x4,...
[ランダムクセス]
x10,x1,x8,x5,x3,x7,x100,x6,x200,...

ここで、馬鹿をさらしている人達は、ランダムアクセスは、毎回
通し番号kを乱数で発生させてからアクセスするものだと誤解している。
それは数学的には0点である。
ランダムアクセスとはそのような定義ではないからだ。
とにかく、「連続アクセスでなければなんでもいい」というのが正しい定義。
だから、キメウチで最初から、
&x10,&x1,&x8,&x5,&x3,&x7,&x100,&x6,&x200,...
というアドレスの列が分かっていて、それを順番にアクセスすれば、
ランダムアクセスの定義にあてはまる。
そしてそのようにしたとき、1回当たりに掛かる時間がO(1)である、
というのが、数学的に正しい見方。
何度も言うが、俺は、数学はほとんど満点だった。

繰り返し言うが、リンクリストに置いて、ノードへのランダムアクセスに
必要な時間は、O(1)が正しい。O(N)と思ってるのは、ランダムアクセスの定義
を誤解している。
O(N)かかるのは、リンクリストに置いて「通し番号からノードのアドレスを求めるのに掛かる時間」
である。リンクリストに置いて、通し番号からノードのアドレスを求めることは、
ランダムアクセスには一般的には不要である。だから、O(1)で正しい。
0189デフォルトの名無しさん垢版2021/11/22(月) 17:29:51.54ID:HWCOZSD4
>>187
だから、それはランダムアクセスの定義では無いんだと何度入ったら分かるんだよ。
どうして、k番目を乱数で与えると思ってるんだ。
ランダムアクセス度は、「ランダム数で与えられたノードでアクセスする」
ことではなく「ランダムな位置のノードをアクセスするためこと」だぞ。

数学的には全く別概念だ。

何でも言うが俺は、数学はほぼ満点だった。
0190デフォルトの名無しさん垢版2021/11/22(月) 17:33:29.42ID:ejqG4gpN
https://play.rust-lang.org/?version=nightly&;mode=debug&edition=2021&gist=8866d679a9e61d53c5b588d0f0d51c45
#![feature(linked_list_cursors)]
fn main() {
use std::collections::LinkedList;
let mut list = LinkedList::from([1, 2, 3]);
let mut cursor = list.cursor_front_mut();
cursor.move_next();
println!("{:?}", cursor.current()); // Some(2)
cursor.insert_after(20); // O(1) insertion
println!("{:?}", list); // [1, 2, 20, 3]
}
0191デフォルトの名無しさん垢版2021/11/22(月) 17:33:38.88ID:HWCOZSD4
例えば、位置が最初から分かっていても、どうやってもランダムアクセスが
遅くなる例としては、テープレコーダーがあげられる。
これは、どう頑張っても、長さNに対して、O(N)の時間がかかってしまう。
繰り返しになるのが、リンクリストの場合は、O(1)だ。
ただし、先頭からの通し番号 k を与えられた時に、データが有るアドレスを計算するのに
掛かる時間は、O(k)だ。
しかし、ランダムアクセスに掛かる時間はO(1)だ。

この違いが分からない人は数学が出来なかったことであろう。
0192165垢版2021/11/22(月) 17:35:33.12ID:43z4eYfr
理屈はもういいので、プログラミングできるならベンチマークを出して、他の言語より遅いことを示してくれませんか?
0194デフォルトの名無しさん垢版2021/11/22(月) 17:38:58.35ID:HWCOZSD4
何故これが重要となるかといえば、実際にこの性質を利用して、
C言語では古くから、リンクリストをO(1)の時間でランダムアクセスして
きたからだ。O(k)ではなく、O(1)だ。

この例としては、リンククリストの中の不連続な100個のノードのアドレスを
どこかの配列にいてれておいて順番にアクセスする例がある。
この場合、一個当りの平均アクセス時間はO(1)、全体に掛かる時間はその100倍で済む。

しかし、アドレスではなく、ノードを通し番号で識別した場合、
一個当りの平均アクセス時間は、O(N)、全体に掛かる時間はその100倍になってしまう。

この意味に置いて、アドレス(ポインタ)でノードを識別することに徹すれば、
リンクリストにランダムアクセスする時間は、O(1)である。

しかし、このようなアクセス法は、Rustは一般的には無理。
0197デフォルトの名無しさん垢版2021/11/22(月) 17:48:40.73ID:43z4eYfr
「Rustだとできない」っていうのはよくわからないし、そこだけ気になってるんだけど、
Rustって参照を持ち回すことがそんなにできないんだ
0198デフォルトの名無しさん垢版2021/11/22(月) 17:49:16.27ID:EEj8G+es
C言語であろうがなかろうが言語に関係なくO(1)は無理
わからない人はコーディングすればすぐわかる
ランダムでkが与えられた時にリンクリストのk番目を常にO(1)で得るためには
全てのk番目の位置を別の配列で保持管理しないといけない
そしてリンクリストで挿入削除が行われるたびにk番目がズレるから保持管理する配列で毎回O(n)を必要とする移動が発生
どんな言語でどんな手法を用いてもO(1)は絶対に不可能
0199デフォルトの名無しさん垢版2021/11/22(月) 17:53:40.47ID:ejqG4gpN
>>198
俺もそう思う
彼の主張にはポインタの配列をケアする時間を含んで無さそうに聞こえたけどw
せっかくのリクリストとは別にアクセス用のポインタ配列をケアするってことも
ふしぎなコーディングだけど
そこまでするなら最初から配列だけでやれって思うけどw
0200デフォルトの名無しさん垢版2021/11/22(月) 17:55:47.65ID:HWCOZSD4
>>198
その別の配列に用意したアドレスに基いてアクセスすれば、立派なランダム
アクセスなんだ。
ランダムアクセスとは、毎回デタラメにアクセスすることでは無いぞ。

テープレコーダーの場合、キメウチで、100, 1, 200, 10, 30, 2, 1000
の位置の7個のデータを取得するには、シーク時間が必要だから、
100+99+199+190+20+28+998 の時間が掛かる。
そしてこの読み取りを2回行ってもまた同じだけの時間が掛かる。
その意味で、ランダムアクセス時間は、テープの長さがNの時、O(N)とされている。

ところが、リンクリストの場合、アドレスが毎回決まっている 7 個のデータ
をアクセスするには、一個当りのノードに掛かる平均時間は O(1)だ。
これを2回行っても同じ。

あなたがおもっているような、シーク時間はリンクリストの場合には不要だから。
0201デフォルトの名無しさん垢版2021/11/22(月) 17:56:50.13ID:HWCOZSD4
>>199
そうでなくて、その配列が既に決まっている場合もあるんだということだ。
それを上手く用意することが出来るケースが現実にかなり有る。
0202デフォルトの名無しさん垢版2021/11/22(月) 17:57:28.92ID:ejqG4gpN
いや配列ケアのほうは時間はそれほどでもないか
挿入削除場所以降のコピーする必要が出るだけで
0204デフォルトの名無しさん垢版2021/11/22(月) 17:59:44.70ID:HWCOZSD4
なぜかというと、アドレスは、ノードを追加した時に分かるから、それをどこかに
記録しておけば「シーク時間」が不要だから。

例えば、100個のノードを任意の位置に追加したとしよう。そのアドレスは、
100個分は既知である。そのアドレスをまたどこかのリンクリストの末尾に
でも順番に追加して全て記録しておいたとしよう。

そうすると、元のリンクリストは、立派にO(1)でランダムアクセスできるんだ。
0205デフォルトの名無しさん垢版2021/11/22(月) 18:00:15.83ID:43z4eYfr
> リンクリストの場合、アドレスが毎回決まっている 7 個のデータをアクセスするには、
> シーク時間はリンクリストの場合には不要だから。

そら、あらかじめアドレスがわかってればできるだけで、別にLinked Listの性質ではないよね
0206デフォルトの名無しさん垢版2021/11/22(月) 18:01:09.38ID:EEj8G+es
>>200
そこでO(1)とは配列のアクセスのみ
つまりリンクリストは全く関係なく配列のアクセスがO(1)だと主張していることに気付こう
そしてリンクリストで削除や挿入が行われるたびにその配列でO(n)の大移動が行われる
結論: O(1)ではどんな言語でもプログラミングできない
0208デフォルトの名無しさん垢版2021/11/22(月) 18:04:00.68ID:HWCOZSD4
>>205
そうでない。
テープレコーダーとリンクリストでは、明らかにランダムアクセスに掛かる時間の
性質が違う。
「アドレスが既知」であるのは、ポインタを全面的に使ったプログラミング法
では当たり前の事だから、リンクリストに置いてシーク時間は不要。
0209デフォルトの名無しさん垢版2021/11/22(月) 18:05:44.36ID:HWCOZSD4
>>206
違う。
ツリーの場合でも、番号ではなく、ノードをポインタで識別することで、
0の時間でシークできる。
リンクリストでも同じ。
通し番号を使おうとするから遅くなってるだけ。
ノードの識別をポインタで統一してしまうと、本当に O(1)でいける。
0210デフォルトの名無しさん垢版2021/11/22(月) 18:07:52.10ID:EEj8G+es
>>204
あなたの主張を整理すると
「k番目をO(1)でアクセスできる配列」は「k番目をO(n)でアクセスできるリンクリスト」よりも優れている、となる
O(1)の部分はリンクリストと全く無関係であることに気付かないとね
ここまで壮大な勘違いをしてるのはおそらくプログラミングをしたことがないのだろうけど
0211デフォルトの名無しさん垢版2021/11/22(月) 18:09:34.28ID:43z4eYfr
アドレスへのランダムアクセスは定数オーダー。そりゃメモリはそういう設計で作られてるんだから当然
テープレコーダーはランダムアクセスできない。これも当然

なんでテープレコーダーと、メモリ上に実装したLinked Listを比較しているのか意味がわからない
何を説明しようとしてるんだろう
0212デフォルトの名無しさん垢版2021/11/22(月) 18:10:17.50ID:ejqG4gpN
>>206
なんか話途中から首突っ込んだけど
結局はそういうしょうもないオチっぽいなこれw
ポインタの指す先のデータ構造に一切関わらず
アクセス用のポインタを回収して配列にするんならそりゃO(1)だもんな
そしてわざわざそれをしたいという動機もよーわからんかった
0213デフォルトの名無しさん垢版2021/11/22(月) 18:12:45.44ID:HWCOZSD4
例えば、データベースの様なものが有ったとしよう。
個人情報がリンクリストに入っているが、ID番号と個人情報は別に配列の中に
入っていて、ID番号の構造体には、リンクリストのノードのアドレスも
入っているとする。
これだと、ID番号を全て巡って、それぞれの個人情報を巡る時、
個人情報の1個当りのアクセスに掛かる平均時間はO(1)だ。
しかし、ノードのアドレスの変わりに、ノードの通し番号を入れてしまって
いたとすると、ノードをシークするためにO(N)の時間が掛かってしまう。

なので、ノードの識別をポインタにしてしまえば、O(1)で、通し番号に
してしまえばO(N)の時間が掛かる。
だから、リンクリストを使う場合には、通し番号ではなく、ポインタを
使うことが推奨されている。ところが、Rustではそれがほぼ不可能。
0215デフォルトの名無しさん垢版2021/11/22(月) 18:15:23.83ID:HWCOZSD4
>>210
いや、ノードの識別をアドレスで行いさいすれば、
リンクリストと配列のランダムアクセスに掛かる時間はどちらもO(1)だから
リンクリストが劣っていることは無い。

なぜなら、乱数で与えられた位置のノードをアクセスする必要は無いから。
ランダムアクセスする場合でも、アクセスすべき位置は、アドレスで決まっている。
シークの時間は不要。
0216デフォルトの名無しさん垢版2021/11/22(月) 18:16:52.13ID:HWCOZSD4
>>214
次の借用規則に引っかかる。
・1個でも書き込みの参照が有る場合、読み込み参照は1つも持てない。
 書き込み参照も1個しか持てない。
0217デフォルトの名無しさん垢版2021/11/22(月) 18:26:59.33ID:5egSOJea
>>214
Rustが次々とC/C++の領域を置き換えていってるように
両者で実現できることは同じ
彼はアルゴリズムとオーダーについてもよく理解できていないだけでなく
Rustについても全く理解していない
0218デフォルトの名無しさん垢版2021/11/22(月) 18:28:27.85ID:43z4eYfr
なるほど。もうちょっとRust覚えたらそういうデータ構造も自分で実装して試してみるよ
0219デフォルトの名無しさん垢版2021/11/22(月) 18:31:34.64ID:HWCOZSD4
>>217
計算時間のオーダーが全く違ってくる。
データベースなどは速度やメモリー効率を高めるために、さまざまな構造を
駆使して作られていることが有り、Rustでは自由に作ることが難しいことが
有り得る。
100万行のテキストエディタの先頭に1000行のデータをペーストするような
時にもリンクリストが大活躍する。単純な配列では遅すぎて駄目。
0220デフォルトの名無しさん垢版2021/11/22(月) 18:34:23.79ID:HWCOZSD4
>>217
あなたは、データ構造やポインタを深く理解して無いか、
高度な実践的プログラミング経験が浅いかのどちらか。
0221デフォルトの名無しさん垢版2021/11/22(月) 18:41:12.00ID:EEj8G+es
>>219
やはりプログラミングしたことがないようだな
そこで50万行目に行く場合に配列併用なし実装だとリンクを50万回たどるO(n)
配列併用あり実装だと50万行目へ一気に行けるO(1)が挿入削除時のたびに配列内で大移動O(n)
つまりO(1)になっているのは配列アクセスのみ
0222デフォルトの名無しさん垢版2021/11/22(月) 18:45:29.95ID:HWCOZSD4
>>221
リンクリストAの中のランダムな位置のノードのアドレスを、
別のリンクリストBに入れておいて、Bの先頭から順番にループすれば、
リンクリストAのノードをランダムアクセスできるが、その時の
一個のノードあたりの平均アクセス時間はO(1)だ。
ここに配列は一個も出てこない。
0223デフォルトの名無しさん垢版2021/11/22(月) 18:51:10.61ID:5egSOJea
>>222
それ、あるkが与えられたときにk番目のアクセスがO(n)になってる
それがリンクリストの性質
ランダムアクセスすなわちk番目のアクセスはO(1)の配列が圧倒的に有利
0224デフォルトの名無しさん垢版2021/11/22(月) 18:54:15.44ID:HWCOZSD4
>>221
それはテキストエディタでは結構問題になる部分だが、
実際的には、ページ単位の大きな移動は文字挿入や文字削除などの編集操作に比べて時々しか
行わないことと、現在位置から相対的な移動距離は大きくないことが多いことから、
行の記憶は配列ではなくリンクリストにしておく手法を取ると良い。
実際に行の記憶を何も配慮せずに配列でやると、ペーストした時にとても遅くなる。
一方、行の記憶をリンクリストにすると、実際問題はかなり快適になる。
スクロールなども速い。
一気に決め打ちの行番号に移動するのはO(N)の時間が掛かることはかかるが、
決め打ちの番号に移動することは、たまにしか行わないので遅くは感じない。
0225デフォルトの名無しさん垢版2021/11/22(月) 18:55:48.29ID:HWCOZSD4
>>223
どうして、あなたは、いつまでたっても、頑なに番号k からノードを
辿ろうとするんだ。
ポインタだと速いのに。
何のためにポインタが発明されたのか理解して無いな。
0226デフォルトの名無しさん垢版2021/11/22(月) 18:59:38.49ID:HWCOZSD4
>>223
ランダムアクセスとランダムに生成した通し番号 k のノードにアクセスする
ことは別の概念だぞ。
0227デフォルトの名無しさん垢版2021/11/22(月) 19:03:37.90ID:kGsgeZzB
結局Rustで実装できないテキストエディタ向けのデータ構造って具体的にはなんなんだ…
ropeもgap bufferもpiece tableも普通にRust実装あるが
0228デフォルトの名無しさん垢版2021/11/22(月) 19:07:47.11ID:HWCOZSD4
>>227
それは、人の知らないものを出してきて、根本問題から目を背けさせる手法。
どんなcrateがあろうと、根本的に出来無い事がRustには有るという話をしてる。
0230デフォルトの名無しさん垢版2021/11/22(月) 19:19:12.02ID:5egSOJea
>>225
まずCプログラマーには常識だけど
インデックスの番号を持つこととポインタを持つことでオーダーOが変わることはない
次に各々への複数のポインタを持つには配列やリンクリストなどの構造が必ず必要となる
いずれにせよポインタを使うことでオーダーOが変わることはない

>>228
そんなウソをついて何がしたいのかさっぱりわからない
0231デフォルトの名無しさん垢版2021/11/22(月) 19:21:02.53ID:HWCOZSD4
>>230
>インデックスの番号を持つこととポインタを持つことでオーダーOが変わることはない
>次に各々への複数のポインタを持つには配列やリンクリストなどの構造が必ず必要となる
>いずれにせよポインタを使うことでオーダーOが変わることはない

なんで、このスレはこんなにレベルが低いの。
0233デフォルトの名無しさん垢版2021/11/22(月) 19:27:10.84ID:DZQ1+JmR
>>232
数学の専門家であってプログラミング経験がないからソースコード出せとの指摘には一切答えられないということかな
0234デフォルトの名無しさん垢版2021/11/22(月) 19:32:17.29ID:fRCpO7Rh
>>194
ここであなたがおっしゃっているのは、以下のような実装のことでしょうか?

Element *array[] = {l0, l1, l2, l3, ...};

lnはリストのn番目の要素
0235デフォルトの名無しさん垢版2021/11/22(月) 19:43:59.25ID:HWCOZSD4
>>234
近いが、初期値が、{ &l5, &l1, &l123, &l25, ... };
のようになっているイメージ。
ただし、実際には、
・初期化子リストには書かず、プログラムの途中でリンクリストに挿入した直後に記録するような
 ことが多い。
・ノードの識別を常にポインタで扱うので、& で書くことは無い。
・固定配列ではなく、それもまたリンクリストにすることが多い。
 なぜなら、リンクリストは効率が良いことが多いから。
0236デフォルトの名無しさん垢版2021/11/22(月) 19:46:52.11ID:HWCOZSD4
>>233
そうではなく、
・大規模すぎて、こういうところには抽出して書ききれない。
・言葉で書いたほうが理解し易いはずだと思った。
 抽象概念を理解しにくい人がこんなに多いスレだとは思わなかったから。
・しかし、これだけ書いても理解できないと言うことは、具体的に書いても
 ますますそのコードの本質的な意味が理解できないと思われる。
0239デフォルトの名無しさん垢版2021/11/22(月) 20:02:20.61ID:fRCpO7Rh
>>235
ある要素が複数のリストに所属するイメージでしょうか
例えば全要素が連なっているリストのn番目、特定の要素だけが抽出された別のリストのm番目に属すといったような
要素の削除に当たっては属するすべてのリストについて前後の要素からの参照を外す
0240デフォルトの名無しさん垢版2021/11/22(月) 20:03:50.15ID:5egSOJea
配列でもリンクリストでも他のコレクションでも全てに言えること
「格納要素が『データ本体でも、ポインタでも、何らかのid番号でも、他のインデックス番号でも、』そこは一切関係なく、様々な操作のオーダーOが変わることはない」
まずこの大原則をID:HWCOZSD4は理解できていないのたろう
だからポインタを使うと魔法のようにオーダーがO(1)になると勘違いしている
0244デフォルトの名無しさん垢版2021/11/22(月) 20:07:17.81ID:HWCOZSD4
>>243
読み込みオンリーに限定して、一切削除もしないという条件なら可能。
ノードの中に書き込んだり、ノードを削除するなら、不可能。
0245デフォルトの名無しさん垢版2021/11/22(月) 20:08:42.39ID:HWCOZSD4
>>244
[補足]
C/C++/Java/C#/JS/Ruby/Python など多くの言語では可能だが、Rust
だけが不可能。
なので、Rustだけが仲間はずれであり、他の言語でできる事ができない。
0247デフォルトの名無しさん垢版2021/11/22(月) 20:11:54.24ID:4Q+A1yLL
>>236
gistでもどこでもいいからコード貼り付けてリンクここに貼ってください
日本語でうだうだ話すより議論が早く終わるでしょうあなたの言うことが正しければ
0249デフォルトの名無しさん垢版2021/11/22(月) 20:14:53.48ID:HWCOZSD4
>>246
デタラメ一言ってんじゃないぞ!!

>>247
具体例を書いても、それはレアケースだの、本質的にはリンクリストの速度では
間違った評価が下るだけ。

そもそも、極簡単な話を書いてるのに理解できないのにコードを書いても理解できる
とは思えない。
そもそも、ランダムアクセスの意味すら理解出来て無い、ここの人達は。
0252デフォルトの名無しさん垢版2021/11/22(月) 20:21:30.15ID:4Q+A1yLL
そもそもRustだって最悪UnsafeCell使えば1変数への多数読み書き参照は保持できるのだが
0253デフォルトの名無しさん垢版2021/11/22(月) 20:27:13.86ID:4Q+A1yLL
>>249
僕はリンクリストの速度がどうこう評価するつもりはあんまりなくて、
他言語で書かれたソースコードが本当にRustでは無理なのかを確認したいだけ

だから、その「Rustでは無理なコード」を見てみたい、と言っている
最悪ソースコードの中身は理解不能なものでもよい
0254デフォルトの名無しさん垢版2021/11/22(月) 20:27:43.67ID:43z4eYfr
>>249
説明するつもりもないのに、お前らはどうせ理解もできないバカだ、俺はいつも数学100点の天才だ、俺を信じろ

とか言ってても狂人扱いされるだけに決まってるじゃん・・・
0256デフォルトの名無しさん垢版2021/11/22(月) 20:50:09.64ID:MtEs+7mt
おれも興味があるな
C++では書けてRustでは書けないコード

リソースを無視すればチューリング完全だろうから
書けないなんて事はないはずで
何かしら制限を付けた上での「書けない」なんだろうけど
0258デフォルトの名無しさん垢版2021/11/22(月) 21:10:18.70ID:ejqG4gpN
>>216
プログラマを守るためそれをさせないのがRustっていう言語ではw
Rc<RefCell>ではいかんの?

https://play.rust-lang.org/?version=stable&;mode=debug&edition=2021&gist=50e9fc65e69dd1859478ee62dde963aa
fn main() {
use std::collections::LinkedList;
use std::rc::Rc;
use std::cell::RefCell;
let mut list: LinkedList<Rc<RefCell<i32>>> = LinkedList::new();
list.push_back(Rc::new(RefCell::new(1)));
list.push_back(Rc::new(RefCell::new(2)));
list.push_back(Rc::new(RefCell::new(3)));
println!("{:?}", list); // [RefCell { value: 1 }, RefCell { value: 2 }, RefCell { value: 3 }]
let mut vec: Vec<Rc<RefCell<i32>>> = Vec::new();
let mut it = list.iter();
vec.push(Rc::clone(it.next().unwrap()));
vec.push(Rc::clone(it.next().unwrap()));
vec.push(Rc::clone(it.next().unwrap()));
println!("{:?}", vec); // [RefCell { value: 1 }, RefCell { value: 2 }, RefCell { value: 3 }]
println!("{:?}", vec[1]); // RefCell { value: 2 }
*vec[1].borrow_mut() = 22;
println!("{:?}", vec[1]); // RefCell { value: 22 }
println!("{:?}", list); // [RefCell { value: 1 }, RefCell { value: 2 }, RefCell { value: 3 }]
println!("{:?}", vec); // [RefCell { value: 1 }, RefCell { value: 2 }, RefCell { value: 3 }]
}
0260デフォルトの名無しさん垢版2021/11/22(月) 21:14:06.15ID:ejqG4gpN
あっコメントはミスってる
実行結果はこちら
[RefCell { value: 1 }, RefCell { value: 2 }, RefCell { value: 3 }]
[RefCell { value: 1 }, RefCell { value: 2 }, RefCell { value: 3 }]
RefCell { value: 2 }
RefCell { value: 22 }
[RefCell { value: 1 }, RefCell { value: 22 }, RefCell { value: 3 }]
[RefCell { value: 1 }, RefCell { value: 22 }, RefCell { value: 3 }]
0261デフォルトの名無しさん垢版2021/11/22(月) 21:17:24.64ID:DZQ1+JmR
Rustの実装 (>>257) はポインタでの直接アクセスではなく配列への添え字アクセスだからオーバーヘッドが大きいとか言い出したらみんなで笑ってあげましょう
0262デフォルトの名無しさん垢版2021/11/22(月) 21:26:20.75ID:7gi7NmEv
>>257
独自のLinkedListで、実装としては配列を持っていて、
ノード間が参照でリンクされておらず、添え字番号でリンクしており、
get(), set()が添え字番号を返して配列要素を返しているので
ゼロコストではないね。

struct LinkedList<T> {
 first_idx_a: Option<usize>,
 first_idx_b: Option<usize>,
 elems: Vec<Elem<T>>,
}
struct Cursor {
 a_idx: usize,
}
fn get(&self, elem: Cursor) -> &T {
 &self.elems[elem.a_idx].data
}
fn set(&mut self, elem: Cursor, data: T) {
 self.elems[elem.a_idx].data = data;
}
0264デフォルトの名無しさん垢版2021/11/22(月) 21:27:14.40ID:5egSOJea
>>257
それで実装も動作も良いけど
_bはどちらも不要
_a.0と_a.1はそれぞれprevとnextと書いたほうが読みやすい
0265デフォルトの名無しさん垢版2021/11/22(月) 21:33:11.94ID:fRCpO7Rh
>>264
_b は単一の要素が複数のリストに属するという要件に対する実装ですね
面倒だったのでメンバーだけ用意して実装はしてないですが
タプル使ってるのも構造体定義が面倒だったため
というかできるできないを実証するための例なので細かいところは適当です
お好きなように修正してください

>>263
>>245
> C/C++/Java/C#/JS/Ruby/Python など多くの言語では可能だが、Rust
だけが不可能
> なので、Rustだけが仲間はずれであり、他の言語でできる事ができない。

というのはほかの言語ではゼロコストで実装できることを意味していますか?
それともRustでも実装できることを認めた上でのただの負け惜しみですか?
はたまたこれを書いたのは自分とは別の人と主張されるのでしょうか
0267デフォルトの名無しさん垢版2021/11/22(月) 21:37:06.49ID:7gi7NmEv
>>265
後半のあなたの主張、おかしくないか。
Rustの参照では無い独自の参照風の様な構造を添え字番号で実装してしまって、
C言語より速度を落としているのだから、ゼロコスト性に反してる。
0269デフォルトの名無しさん垢版2021/11/22(月) 21:38:56.97ID:fRCpO7Rh
>>267
あらゆる言語の中でRustだけが実装できないという主張は撤回されて
CにRustは劣るという主張へと変更されるのですね?
0270デフォルトの名無しさん垢版2021/11/22(月) 21:49:14.11ID:EEj8G+es
>>257
elements_aはinto_iterにしたらあかんの?と思ったけど
2つ持った時の前半用として用意した意味なのかw
0271デフォルトの名無しさん垢版2021/11/22(月) 21:56:48.89ID:7gi7NmEv
>>269
1. データを格納している場所が配列になっているが、動的に長さを長くしようとすれば
 動的配列と同様のコピー動作が生じてしまうから、その実装は、本来のLinkedListの
 性質とはかなり異なる。リンクリストは速度的に安定である事が重要なのに、
 この性質により、動的配列と同様に、時々大規模コピーが生じて、スパイク的に
 速度が遅くなる減少を伴うことになってしまう。このようなスパイク的な
 速度低下は、twitterかFacebook のどちらか忘れたが、どっかのSNSでも問題
 になっていた。
2. アクセスするときに、番号を配列のアドレスに変換する動作を毎回行っている。
0272デフォルトの名無しさん垢版2021/11/22(月) 22:00:19.83ID:7gi7NmEv
>>271
[補足]
誤解を招いて議論に混乱を来たしそうなので捕捉しておくと、
271の2で書いた「番号」は、リンクリストの先頭からの通し番号の事ではなく、
今回示されたリンクリスト風のコードで、内部で用いられている配列の添え字番号
のことで、リンクリストの先頭からは、辿っていっても、連続した番号には成ってないもの。
0273デフォルトの名無しさん垢版2021/11/22(月) 22:05:48.24ID:fRCpO7Rh
>>271
あらゆる言語で実装できないがRustでは実装できない
他の言語だと O(1) だが Rustだと O(N) になる
という主張を撤回されたと理解しました

そういうことでしたら私の方から言うことはなにもありません

またアロケーションについてはVecを実装が工夫されたコンテナ型に変えることで対応できそうですね
実装詳細のないまま議論してもしょうがないトピックなのでこれ以上こちらからレスを重ねることはやめます
ありがとうございました
0274デフォルトの名無しさん垢版2021/11/22(月) 22:10:00.62ID:7gi7NmEv
>>271
[追加]
3. そこにさらに削除メソッドを実装したとしよう。
 削除したノードに対する番号が、どこかのCursorの中にまだ生きた状態に
 なっている場合、ダングリング参照と似た現象が起きる。
 削除したノードの中を参照できてしまうのだ。
0275デフォルトの名無しさん垢版2021/11/22(月) 22:15:27.68ID:7gi7NmEv
>>273
その主張、Rustの中に超軽量のインタプリタの様なものを載せておいて、
そのインタプリタの中ではランダムアクセスがO(1)のリンクリストが
完全に実装できることを示しただけだね。
しかも、追加すると、時々、大規模なメモリーコピーが生じるし。
newやmallocではそのようなメモリーコピーは生じない。
ノードを追加しても、リンクリスト中の他のノードの本当のマシン語レベルでの
線形アドレスが固定で変化し無いし。
あなたの実装では、それが変化してしまう。相対アドレスは変化しないが。
ベースアドレスが変化している。
0276デフォルトの名無しさん垢版2021/11/22(月) 22:19:00.36ID:fRCpO7Rh
>>274
generational arenaという手法を利用することでダングリングポインタ的アクセスを検知してハンドリング可能になります
0277デフォルトの名無しさん垢版2021/11/22(月) 22:19:03.44ID:7gi7NmEv
>>274
[補足]
実質的なダングリング参照が起きるということは、Rustのもう一つの柱である
ところのメモリー安全性が部分的に壊れてしまってるということだ。
0278デフォルトの名無しさん垢版2021/11/22(月) 22:23:12.75ID:7gi7NmEv
>>276
動的コストを掛けていいなら、C++でも安全性の高いものは作れるぞ。
ポインタも正しいメモリーブロックを指していることを動的に確認した後で
実際に参照するようなことは、C++でも出来るから。
Rustも配列の範囲チェックはやっているが、配列以外のアドレスでも、動的に
チェックしようと思えばいろいろなチェック法はある。
その一つの方法が、アドレスではなく、あなたが書いたような配列の中の
番号方式にしてしまうこと。
番号に対する配列要素がNULLになっていれば、動的にエラーを出力して
アプリを停止させる、などの方法が有る。
0280デフォルトの名無しさん垢版2021/11/22(月) 22:36:23.68ID:7gi7NmEv
>>265
>> C/C++/Java/C#/JS/Ruby/Python など多くの言語では可能だが、Rust
だけが不可能
>> なので、Rustだけが仲間はずれであり、他の言語でできる事ができない。
>というのはほかの言語ではゼロコストで実装できることを意味していますか?
>それともRustでも実装できることを認めた上でのただの負け惜しみですか?

分かった。ゼロコストで無くて良いなら Rustでも実装できるということだね。
なるほど、今回の実装法のような裏技の発想は無かったよ。それは認める。
でも、ゼロコストでなくなるということは、RustがC/C++の代替になるという
説には反することになるね。

それと、C++, Java, C# では最初から標準ライブラリ的なもので最初から実装済み
なのに対して、あなたのやり方は、少なくとも標準のLinkedListではないね。
Cursorも標準のものとは別。
0282デフォルトの名無しさん垢版2021/11/22(月) 22:44:50.09ID:7gi7NmEv
>>281
何がしたいって、C/C++/C#/Javaでは、LinkedListへのアクセスがO(1)で
自由自在に出来るのに、標準のRust実装では出来ないことが問題なんだ。

それに、今回示された実装法では、内部では配列で実装されているから、
ノードを追加してい言って、配列の要素数を超える時には、新しい配列を
コピーして内部でコピー動作が生じる。これは、C++のnewよりも遥かに
遅い動作になってしまうし、スパイク的に時々生じるから速度的な安定性
が求められるソフトでは好ましくない現象。

また、実質的なダングリング参照的が生じることも指摘した。

結論は、このやり方で、C/C++などと同じO(1)にはなったものの、安全性も失われ、
ゼロコスト性も失われ、C/C++の実装に比べて速度的に不安定でありスパイク的に
遅くなるということだ。
0283デフォルトの名無しさん垢版2021/11/22(月) 22:51:04.06ID:0LbM6y2O
>>282
「LinkedListへのアクセスがO(1)で自由自在に出来る」
が正確にはどういう意味かと聞いているんだ

>>257の実装は忘れなさい
0286デフォルトの名無しさん垢版2021/11/22(月) 22:57:09.11ID:7gi7NmEv
>>283
>「LinkedListへのアクセスがO(1)で自由自在に出来る」
>が正確にはどういう意味かと聞いているんだ

Cの場合、ポインタでアクセスすれば、O(1)でリンクリストの
ノードを参照できるし、削除も出来る。
削除しても、他のノードのアドレスは変化しないから、ポインタも
書き換える必要も無い。
配列だったら、削除するとそれより後ろのノードの番号が全て
変化してしまうので、書き直さなくてはならない。
リンクリストでも、先頭からの通し番号を識別番号に
している場合には、同様にそれ以後のノードの全ての番号を書き換えないといけない。

リンクリストのノードにO(1)でアクセスするというのは、ポインタでアクセスすれば
当たり前の事で、どう説明していいのか分からない。マシン語では、間接参照の
[アドレス]
だけの話だから。
コンピュータの基礎から学び直してもらわないと理解してもらえないかも知れない。
マシン語を学んで欲しい。
0287デフォルトの名無しさん垢版2021/11/22(月) 22:57:21.67ID:0LbM6y2O
コンテナと各要素の&mutと&が同時に取れない件はsplitして借用の単位を分けるべし
Vec::split_at_mutと同様の発想
0289デフォルトの名無しさん垢版2021/11/22(月) 23:01:06.85ID:7gi7NmEv
>>285
どっちがデマだと思ってるのか知らんが、俺のはデマじゃないぞ。

実際に、今回の実装を示した彼は、俺の言ってることはある程度正しく理解していた。
つまり、基本的にデマじゃないということを理解した人がいるということだ。
ただし、彼は、ゼロコスト安全性である、ということを無視して独自実装したり、
参照を独自に修正したものを勝手に導入した誤魔化しがあったのが残念であった
だけだ。
つまり、俺の主張自体は、彼は本当は理解している。
理解しているが、悔し紛れに詐欺めいた独自実装をしたことだけが残念なだけだ。
0291デフォルトの名無しさん垢版2021/11/22(月) 23:13:17.79ID:5egSOJea
>>290
デマを流すのはそろそろやめとけよ
RustはRefCellもあるし複数からポインタで指しつつ書き換えもできるぞ
0292デフォルトの名無しさん垢版2021/11/22(月) 23:14:41.21ID:7gi7NmEv
>>291
そもそも、RefCellは、動的チェックが入るからゼロコストではない。
C には存在しないコストが新たに導入される。
0294デフォルトの名無しさん垢版2021/11/22(月) 23:15:41.59ID:NDd1353W
リンクトリストな?
0297デフォルトの名無しさん垢版2021/11/22(月) 23:18:40.37ID:7gi7NmEv
>>295
C++と同じ事が出来るのに「ゼロコスト」で「安全」、と謳ってるのが間違いだと
言ってる。
間違いというより、デマや誇大宣伝。
0298デフォルトの名無しさん垢版2021/11/22(月) 23:21:22.25ID:0LbM6y2O
>>290
そうだ、最初からそう言えばよかったんだ
蓋を開けてみればO(1)なんかまるで関係無いじゃないか

でそれに対して>>287という策があるわけだがどう思う?
0299デフォルトの名無しさん垢版2021/11/22(月) 23:22:12.49ID:7gi7NmEv
>>295
「排他制御」とは、マルチスレッドプログラミングで使う用語なのだが、
本当にその意味で使ってるか?
0300デフォルトの名無しさん垢版2021/11/22(月) 23:22:18.49ID:EEj8G+es
>>292
ゼロコストって他のことでもそうだけど全くコストがかからないってことではない
必要最低限のことのみでそれ以外はゼロコストってこと
今回のRefCellならば並行プログラミングの時の書き換え競合が起きないことを保証する
RefCellはゼロコスト
ゼロコストでないと主張するならば他の対処方法を述べよ
0302デフォルトの名無しさん垢版2021/11/22(月) 23:28:31.00ID:7gi7NmEv
>>300
俺も正直言うとRefCellとか出てくると複雑すぎてよくわからなくなってくるが、
RefCellは内部可変性に対するものだから、並行プログラミングを使わない時
にも使うことがあるはずだが。
0303デフォルトの名無しさん垢版2021/11/22(月) 23:28:31.66ID:NDd1353W
Rustは安全性を追求した言語でC++と比較する物ではない。
比較するならRubyが妥当。
0304デフォルトの名無しさん垢版2021/11/22(月) 23:30:51.55ID:7gi7NmEv
>>303
つまり、CやC++の代替には成りえない。
アプリレベルであってもC/C++の全てをカバーすることは出来ない。
0305デフォルトの名無しさん垢版2021/11/22(月) 23:33:19.88ID:WXoW4mOX
コンパイラに安全性を保証してほしければ実行時のコストを払ってRefCellを使えばいいし、
そのコストを払いたくなければunsafe 使って自分で安全性を保証すればいいって話なんだが
0306デフォルトの名無しさん垢版2021/11/22(月) 23:35:15.39ID:4Q+A1yLL
必要最低限のunsafeを使うのは大前提で、
それでもリンクリストがどうたらって話じゃなかったっけ・・・??
0307デフォルトの名無しさん垢版2021/11/22(月) 23:36:31.09ID:NDd1353W
だからリンクトリストな?
0308デフォルトの名無しさん垢版2021/11/22(月) 23:38:22.71ID:5egSOJea
>>299
シングルスレッドマルチタスクでも競合は起き得る
そのため書き込み権限がある者がある瞬間に複数存在しないことを保証する(排他制御)ためにRefCellがある
マルチスレッドの場合は並列に起き得るからもっと厳しくてRefCellではダメでMutexやRwLockを使う
0309デフォルトの名無しさん垢版2021/11/22(月) 23:39:08.56ID:NDd1353W
Rustは安全性を追求した言語でC++と比較する物ではない。
比較するならVBAが妥当。
0310デフォルトの名無しさん垢版2021/11/22(月) 23:40:06.95ID:NDd1353W
RustがC++をライバル視してきて非常にウットオシイ。
貴様のライバルはJavascriptだろ。
0311デフォルトの名無しさん垢版2021/11/22(月) 23:41:22.24ID:7gi7NmEv
>>291
LinkedListの中のノードへの参照を10個持っている状態で、
その参照を使って1個のノードを削除しようとしてコンパイルは通るか?
0312デフォルトの名無しさん垢版2021/11/22(月) 23:42:38.96ID:0LbM6y2O
>>301
safeであるためには必要なコストだと思うけどね
mutabilityが前後のノードに影響するデータ構造だから仕方がない
0315デフォルトの名無しさん垢版2021/11/22(月) 23:55:11.62ID:4Q+A1yLL
>>311
参照先自体を削除するんじゃなくて、参照先からさらにnextとかprevたどってどっかのノードを削除するってこと?
参照先自体を削除するのはRustに限らず問題でるよね
0316デフォルトの名無しさん垢版2021/11/22(月) 23:58:04.28ID:7gi7NmEv
>>315
参照先を削除するのは普通なことで、安全に行えるぞ。
参照とは、つまり、識別番号の代わりに使うものだからな。
参照はオブジェクトに付けられた名前みたいなもんだから、
逆に言えば、参照先を削除できないなら、削除する方法がほぼ無い。
0317デフォルトの名無しさん垢版2021/11/23(火) 00:00:50.13ID:1c3aeddQ
何の話についてもまずは具体的なC言語のコードを示すべきじゃないかな
そうすればRustのコードを2種類みんなが出してくれるよ
 ・1つは元のC言語と同じ安全度で場合によってはunsafeを用いて実装
 ・もう1つはメモリ安全性を保証してunsafeを使わずに実装
つまり「C言語で出来ることはRustで必ず出来る」+「Rustではメモリ安全性を保証した実装も可能」
明らかにC言語よりもRustの方が能力も高く優れている
0318デフォルトの名無しさん垢版2021/11/23(火) 00:00:51.12ID:16zHq7La
>>314
残り9個の参照はそのノードが削除されたことを知る術がないからダングリングポインタになるってことだろ
0319デフォルトの名無しさん垢版2021/11/23(火) 00:08:02.67ID:xJBrssBV
>>318
本来は、明らかに別のノードであれば問題ない。
C++では普通に安全にそれが行える。
リンクリストの中に、A, B, C という名前の人のデータが入っていて、
それぞれに対して1つずつそれぞれ、ポインタ pA, pB, pC が存在している時に
ポインタ pA を介してAを削除しても、B, C へのポインタ pB, pC は残っていて、
値も変更されることも絶対に無いから完全に安全。
Aさんのデータを削除する場合にはこのようなことが起きるが、その時には、
delete pA の後、pAを捨ててしまうだけで全く安全。
pB, pC は何事も無くまったく安全に残せるし、何のバグも入らない。
こんな単純なロジック、何の問題も無い。
0321デフォルトの名無しさん垢版2021/11/23(火) 00:16:47.17ID:1c3aeddQ
>>319
それだと>>311の条件を満たしていないのでやり直し
 ・いずれにせよC/C++で書けるコードはそのままの形でそのままの安全度で必ずRustでもunsafeを用いて書ける
 ・更にRustでは安全性を保証する形でunsafeを用いずに実装することもできる
C/C++よりもRustのほうが明白に能力が高い
0323デフォルトの名無しさん垢版2021/11/23(火) 00:21:41.44ID:/rTkTwIT
>>319
C++でノードへのポインタは実装依存な方法でしか取れないよ
pAその他は本当にポインタ?イテレータではなく?
0324デフォルトの名無しさん垢版2021/11/23(火) 00:21:54.64ID:xJBrssBV
>>321
何度もしているが、それはフェイク。
Cできることのうち、Rustでは追加コストを掛けずにはsafeモードで出来ないことはたくさん有る。
unsafeモードを使いまくれば別。
しかしそれではRustを使う意味が無い。
0327デフォルトの名無しさん垢版2021/11/23(火) 00:25:21.42ID:xJBrssBV
>>326
Rustの売りはゼロコスト+安全性にあるからだよ。
どちらが掛けても意味が無い。
ゼロコストで無いなら既にC#やJavaがある。
安全で無いなら既にC++がある。
0328デフォルトの名無しさん垢版2021/11/23(火) 00:26:18.34ID:6/+wazXE
ああ、なるほど
安全性を考慮していないCのLinked Listと、安全性が保証されたRustのLinked Listを比較して、
Rustは遅い、できることが少なくて不便だ、みたいなことを述べてたわけか

Cでもメモリリークしないようにして、スレッドセーフにするとかしたら、途端に大変になりそう
0332デフォルトの名無しさん垢版2021/11/23(火) 00:31:19.33ID:xJBrssBV
>>330
複数のノードへの読み書き自由なアクセスの速度をO(1)を保ったままで、
RustではunsafeをLinkedListのメソッド内には閉じ込めることが基本的に
出来ない。基本的に、と言ったのは、先ほど彼が示したリンク先の独自
実装の様に、ゼロコストであることを諦めてコストを掛ければできる
ようになるから。ただし、その場合、スパイク的にO(N)の時間でコピー
動作が発生してしまう。
0333デフォルトの名無しさん垢版2021/11/23(火) 00:32:59.52ID:xJBrssBV
>>332
[補足]
スパイク的なコピーの発生だけでなく、普段からコスト増加もある。
ベースアドレス + 相対アドレスでアクセスするから。
0337デフォルトの名無しさん垢版2021/11/23(火) 00:49:14.22ID:xJBrssBV
>>336
1つのリンクリストの異なる10個のノードに対する10個のmut参照を同時
に持ち事は出来ないので、O(1)でアクセスできないからだ。
0339デフォルトの名無しさん垢版2021/11/23(火) 01:08:49.01ID:8Ju98kPx
Rustだと確かに複数個所のノードへの可変参照を得るのはunsafeメソッドになるだろうね
そのノードが全部別々であることが保証できないから
でもそれは他の言語でも同じで、例えば1のノードに複数の可変参照があって、
1の参照がノード消したらまずことになる

そしてunsafeを許すのなら、内部実装でUnsafe Cell使えばコンパイラからの見た目は不変参照になるから、
オーバーヘッドなしでそういうのは実装可能(ただしstdのLinkedListはそのようにはなっていない)

んで、複数個所のノードへの可変参照を得るというのは相当レアな操作なはずなので、
それはunsafeにしてもAPIの使い勝手としては全然問題はない
0340デフォルトの名無しさん垢版2021/11/23(火) 01:37:22.61ID:1c3aeddQ
あるC/C++コードがあった時
(A) 常にRustではC/C++コードと同じ安全度で(必要時はunsafeを用いて)実装できる
(B) ほとんどのケースでRustでは安全なコードを(unsafeを用いずに)実装できる

つまりRustの能力はC/C++を上回っている

言い換えると
C/C++を捨ててRustを使えば
(B) ほとんどのケースで安全性を保証する形で実装できる
(A) 残りのレアケースでもC/C++と同じ安全度で実装できる

したがってC/C++を用いずにRustを用いたほうがよい
0341デフォルトの名無しさん垢版2021/11/23(火) 05:32:01.67ID:RKGfozTd
安全性よりも、
とにかくパフォーマンスや使用リソースが最重要な用途がある
そういう所でC/C++が使われる

C/C++は少なくとも今後20年は使われ続ける
0344デフォルトの名無しさん垢版2021/11/23(火) 13:48:55.03ID:VKZug2mU
いや、あわしろ氏もC++は窓から投げ捨てろと言ってる。
0345ハノン ◆QZaw55cn4c 垢版2021/11/23(火) 14:00:24.39ID:A++o7U7T
>>344
その、あわしろ氏とやらは、では、なにを推薦しているのでしょうか?
0346デフォルトの名無しさん垢版2021/11/23(火) 14:20:23.73ID:BTZW3nye
ほんとRust気持ち悪いなw
リンクリストのような単純な構造でSTLでもboostでもそれ自体が「安全でない」ことはめったにない。
バグや脆弱性を作りこんでしまうのは多くは固定長のバッファに対するパース処理などで、確かに各種の
*nixコマンドなんかはRustで書いて貰ったほうが良い場合があるが、C/C++の数msが致命となる世界で
Rustが一般的となることはない。そんな布教をやってるから嫌われるんだよw
悔しかったらOpenSSLとか書き直して”安全なコード”で出してみろよ?WebkitにC/C++を排除させて
Rustだけにさせてみろw
0347デフォルトの名無しさん垢版2021/11/23(火) 14:29:53.22ID:VKZug2mU
いまさらC++やってるようでは時代についていけない老害という評価しかない。
0348デフォルトの名無しさん垢版2021/11/23(火) 14:45:56.12ID:CrSl9z1L
Linusも老害だしChromeコミッターも全部老害、気持ち悪さNo1のRustたちが敵を作りまくる自己評価で
あらゆるスレで暴れてる
0351デフォルトの名無しさん垢版2021/11/23(火) 14:57:43.30ID:2khltGI7
twitterでも、RustはHaskell程度にしか発言されて無い。
一方、C 言語 で検索すると一日分でも見ることが不可能なくらい大量に
発言されてることが分かる。
twitterでは「C++」というキーワードでは検索できないので推定するしかないが、
C 言語以上であろう。
0352デフォルトの名無しさん垢版2021/11/23(火) 15:54:02.42ID:hMtNqdGd
>>340
>つまりRustの能力はC/C++を上回っている
ダウト。
安全面に置いては上回っているが、効率面では下がるケースがかなりある。
0353デフォルトの名無しさん垢版2021/11/23(火) 16:13:02.54ID:hMtNqdGd
・速度を落として安全性を高めたものは、既にJavaやC#がある。
・Rustが仮に速度面ではCに比べて余り遅くならないケースが多いと
 仮定しても(この仮定には嘘があるのだが)、使いこなすのがJavaやC#
 に比べると難しい。

特に参照関連だけでも、Option, Box, Rc, Arc, Cell, RefCell, Cursor, ref, &
の理解が必要な他、mut &'a などの表記、
let mut a : mut &:T = mut& b

Option<Rc<RefCell<T>>> a;
new Box<T>( T {・・・} );
のような解読が難しいシンタックスも多い。
このような複雑な表記は、JavaやC#には存在しない。

また、& と * の違いもあれば、& と ref の違いも有る。
let文ですらパターンマッチング方式になっているので Cのポインタの 10倍理解が難しい。

つまり、普通IQ者には理解が難しい。
逆に高IQ者は、C++でも安全に使えるし、C++を安全面では余り問題を感じて無い人が多い。
0354デフォルトの名無しさん垢版2021/11/23(火) 16:19:09.75ID:hMtNqdGd
>>353
さらに言えば、
・「自動参照外し」は便利だとされるが、逆に勝手に参照が外れることで、
 他人の書いたコードの理解が難しいことがある。明記してるコードと
 省略してるコードが同じことを意味してるのが理解しにくいので。
・&の意味が、let文の左辺ではパターンマッチング、右辺では参照、
 の意味になっているので混乱しやすい。左辺では参照をはずす意味
 になってしまう。
・&は、reference(参照)演算子と呼ばれるのに、ref という演算子もあるが、
 これは、意味がかなり違うため、混乱し易い。
・nullポインタを代入するポインタは、Option<Box<T>> のように長くなる。
・ライフタイム注釈が発展途上中なのか、特に構造体に関するライフタイム注釈
 のドキュメントが少なく、例で説明されるだけで、根本的な意味を書いた
 ドキュメントが存在して無い。
0356デフォルトの名無しさん垢版2021/11/23(火) 18:18:27.96ID:VKZug2mU
LinuxはRustを第二言語と位置づけ、カーネル開発に積極利用する計画です。
0357デフォルトの名無しさん垢版2021/11/23(火) 18:21:55.09ID:1c3aeddQ
C/C++/Rustをやってきた人ならRustが圧倒的にプログラミングしやすいことで一致している
調査結果でもRustが連続1位を続けていることからも客観的に明白
0358デフォルトの名無しさん垢版2021/11/23(火) 18:23:28.79ID:VKZug2mU
あわしろ氏もC++は終了する言語と言っています。
0361デフォルトの名無しさん垢版2021/11/23(火) 19:25:27.46ID:1ymEsXZx
>>359
let mut a : mut &T = mut& b
Box<T>::new( T {・・・} );
だったかも知れんな。
複雑すぎるし、C++との違いが大きすぎて覚えてない。
C++ だと、new クラス名で、Rubyだと確か、クラス名.new。
Rustは、後者に近い書き方だから、書き方だけを見てもRustはC++とはやはり遠い。
0362デフォルトの名無しさん垢版2021/11/23(火) 19:43:48.41ID:VKZug2mU
RustはRubyの影響を受けた言語。
大変使いやすい。
0363デフォルトの名無しさん垢版2021/11/23(火) 19:51:13.12ID:1ymEsXZx
>>362
いくつか本を読んだが、スクリプト言語的な範囲で使うならばそうかも知れん。
しかし、C++やCのようにポインタを駆使したリンクリストやツリー構造の様な
ものを効率よく高速に、メモリーも節約しながら扱うには、Rustはとても
複雑になる。訳の分からんCell,RefCellなどと組み合わせる必要があることも多い。
0365デフォルトの名無しさん垢版2021/11/23(火) 19:59:41.90ID:VKZug2mU
いまどきC++使ってるのは老害でしょう。
すぐにRustを始めるべきです。
0367デフォルトの名無しさん垢版2021/11/23(火) 21:01:08.57ID:VKZug2mU
低能が何か申しておりますw
0374デフォルトの名無しさん垢版2021/11/24(水) 10:49:35.25ID:kXzWnsgO
仮に泡白という人物が実在したとしても
ここで連呼されるのは本人も迷惑してるんじゃないかな
0375デフォルトの名無しさん垢版2021/11/24(水) 11:15:10.51ID:vbixrgR4
Ubuntu Linuxや OpenOffice系の洋書の翻訳家に、
「あわしろいくや」という人物がいるようだ。
0377デフォルトの名無しさん垢版2021/11/24(水) 17:09:21.00ID:5wn/1hS5
>>373
CとRustそれぞれでコードを書いてみることをおすすめします
計算量オーダーが変わるアルゴリズムレベルの検討ならともかく
コンパイラの最適化でいくらでも性能が変わりうる実装の詳細についてはまず性能測定するのが常識だと思います
0378デフォルトの名無しさん垢版2021/11/24(水) 17:29:56.67ID:mlqzRKjQ
リンクリストで頑張るより配列のほうが色々捗る場面も多々あるよな
キャッシュが効いてるとこ読むときの速度は目を見張るもんがある
ヒープで飛び飛びになったデータ構造はその点で恐ろしく不利
それを知ってる人は実測した結果で語る
0379デフォルトの名無しさん垢版2021/11/24(水) 19:53:47.71ID:6QwWetEE
21世紀にもなってC++使ってるのは頭がおかしい。
0380デフォルトの名無しさん垢版2021/11/24(水) 19:54:39.96ID:6QwWetEE
Linusは20世紀の頃からC++は駄目だと言ってた。
天才。
0382デフォルトの名無しさん垢版2021/11/24(水) 22:43:39.16ID:RtLWv5R+
linusのc++否定ってのは当時の実装のバギーさとオブジェクト指向に対する否定だな。
関数型流行ってる今から見ると割と普通のこと言っとるわ。
0386デフォルトの名無しさん垢版2021/11/25(木) 02:58:46.76ID:6PNOZvLH
ここまでのまとめ
(1) ほとんどの用途でLinkedListよりVecの方が有用
(2) Rustの標準ライブラリにはLinkedList型もVec型もどちらもある
(3) もしLinkedListやVecを使っても実現できないならまずはそのRustコードを示すべき
(4) 仮に超レアケースがあったとしてもRustでは自分で自由に必要な型を作ればよい
0391デフォルトの名無しさん垢版2021/11/25(木) 16:34:58.88ID:ug4Dh0aR
>>386
様々な言語の中でRustだけ linked list の任意の要素にO(1)でアクセスできないというのは嘘だった
も追加で
0392デフォルトの名無しさん垢版2021/11/25(木) 20:15:57.40ID:SwFLZgNz
macro記述と言語がまるで別言語、いちいちウザいアトリビュート。letは固定を意味するのではなく式展開
何種類もある「文字列」、それに生えている似たようで意味が違ういっぱいのfn(これはトレイトのせい)
わざと敷居を高くしてるとしか思えん
0393デフォルトの名無しさん垢版2021/11/25(木) 20:31:51.42ID:6PNOZvLH
>>392
> letは固定を意味するのではなく式展開

letは常に成功する構造パターンマッチングにすぎないよ
if letは成功か失敗か不明な構造パターンマッチング
今どきの言語ならば左辺値にパターンが書けるのが普通

> 何種類もある「文字列」

文字列はヒープにあり伸縮可能なStringとそうでないstrの2種類しかないよ
ヒープを意識する言語なら2種類ある
あとは文字列の参照として&strがあってその本体はヒープにあろうがなかろうが同じ扱いできるだけ
0398デフォルトの名無しさん垢版2021/11/25(木) 21:25:33.18ID:88pS2ZzI
まとめ
・どの言語でもリンクリストでk番目を得るにはO(n)かかる
・そのk番目を配列で持てばO(1)だがそれはリンクリストではなく配列アクセスのコスト
・リンクリストのk番目を保持する配列を維持するには削除挿入のたびにO(n)の移動が生じる
・これらは言語に依存しない
0400デフォルトの名無しさん垢版2021/11/25(木) 21:38:29.78ID:beDf3C1p
それが低いレイヤーをやるってことだわな。
それを他の言語のせいにするrust野郎はクソってことだよ。
0401デフォルトの名無しさん垢版2021/11/25(木) 22:13:10.27ID:88pS2ZzI
誤解している人が居るようなので正しい情報
・Rustの通常のプログラミングでCStrやOsStrが出てくることはない
・そこでファイルやディレクトリやソケットを操作してもCStrやOsStrは出てこない
・つまりRustで使う文字列はstrとヒープのStringの2種類しかない
・CStrやOsStrはFFIを書く人のみが用いるのでほとんどの人には無縁
0403デフォルトの名無しさん垢版2021/11/25(木) 22:30:32.62ID:6PNOZvLH
>>402
Rustで未だ対応していない未知のものが出現した時にその対応する人だけがCStrやOsStrを用いる
その時のその人を除き、全ての人はCStrやOsStrなんか知らなくてもRustでプログラミング可能
0405デフォルトの名無しさん垢版2021/11/25(木) 23:16:52.42ID:/vPuyV+m
他の言語がごまかしている箇所を正確に扱えるのがrustの強みでもありめんどくさいところでもある
0406デフォルトの名無しさん垢版2021/11/25(木) 23:45:28.39ID:sK32tKJd
Rust擁護マンでも標準の文字列(String/str)以外がFFIのみというのはさすがに筋悪に見える
Rustで標準の文字列をUTF8のバイト配列(ヌル文字終端不採用)としたことによる弊害って側面が割と強い
でも他言語みたいにそこしっかりしないとなるとそれはそれでめんどくさいから結局のところトレードオフ

でもOsStrめんどいわ
0407デフォルトの名無しさん垢版2021/11/26(金) 00:54:57.87ID:Ye0bskEh
文字列エンコードを規定しないとそれはそれで移植性に問題あるし難しいところ
WTF-8なる概念必要になったりとにかくWindowsが悪いという気はする
0408デフォルトの名無しさん垢版2021/11/26(金) 03:23:02.14ID:FqYYA0QW
>>391
嘘を書くな。
正しくは、Rustは配列を使って独自実装しないとO(1)には出来無い事が明らかに成った。
参照だと借用規則で出来なくて、配列の添え字番号だと単なる整数なので借用規則の
適用範囲外だからできる。添え字番号をポインタの代わりに使って、独自に
リンクトリストを実装することで初めて、O(1)になる。
しかし、O(1)になっても、「係数」が大きくなり、1アクセスに20クロックくらいかかる。
配列の範囲チェックと、配列アクセスのための乗算と加算が追加で必要になるため。

一方、C、C++、C#、Javaではそんなことしなくても最初からO(1)。
0409デフォルトの名無しさん垢版2021/11/26(金) 03:24:19.18ID:FqYYA0QW
>>398
お前みたいなやつは、一度殴ってやりたい。
匿名掲示板だからと言って、でたらめを書くな!!
ばか者!
0411デフォルトの名無しさん垢版2021/11/26(金) 03:33:50.05ID:FqYYA0QW
>>398は、数学できない。
細かい点が全然分かって無い。
リンクリストでは、「k番目にアクセスする」と言っても、次の二種類ある。
1. (乱数などで)整数 k を与えられて、ノードを探す。
 この場合、どうしても、O(N)、O(k)の時間がかかる。
2. 既に追加したノードを、もう一度アクセスする。
 これには、C、C++、C#、Javは、O(1)しかかからない。
 しかも、C、C++だと 1 クロック。
 Rustだと配列と添え字番号を使って独自実装しなければ、
 基本的にO(N)、O(k)かかる。独自実装した場合、
 O(1)ではあるが、20〜50クロックくくらいかかる。
 
0413デフォルトの名無しさん垢版2021/11/26(金) 03:40:28.33ID:FqYYA0QW
>>411
[補足]
実際、>>257 の独自実装は、Rustでも、任意の場所のノードをO(1)で
アクセスできるが、1アクセスあたりに一般的なノードサイズでは
20〜50クロック掛かる。

悪いが、QZが出てくると話がややこしくなる。
かわいそうだが、単刀直入にいえば、QZは頭が良くないので、
レベルが全体に下がってしまう。
ようは、レベルが違う人は、教室を分けないとめちゃくちゃに成る。
レベルというのは熟練しているかどうかではなく、生まれつき決まっていて、
直すことが出来ない。
すまん。
0414デフォルトの名無しさん垢版2021/11/26(金) 03:46:37.90ID:FqYYA0QW
>>398
>・どの言語でもリンクリストでk番目を得るにはO(n)かかる
これは間違いである事は何でも説明した。例えば>>411

>・そのk番目を配列で持てばO(1)だがそれはリンクリストではなく配列アクセスのコスト
これも間違いで、C、C++、Java、C#では、配列で持たずに、直接、ポインタや参照
で持っても、O(1)でアクセスできる。
Rustでは、借用規則が邪魔して、複数の読み書き参照を同時に永続的に保持できないので、
「k」のような番号でしか場所を維持できないため、そんな風になってしまうだけ。
だから、配列と番号を組み合わせてやっとO(1)にできる。
C、C++、Java、C#では、ポインタや参照を永続的にいつまでも保持できるので
配列を使わなくても O(1)でアクセスできる。
その際、「シーク」動作は必要ない。つまり、先頭から k 番目までを辿る必要が
なく、いきなり、k番目に 1 クロックでアクセスできる。
Rustでは、それが、一般的には出来ない。Rustでも、
局所的に1個のノードだけに限定すれば出来る。
0415デフォルトの名無しさん垢版2021/11/26(金) 04:02:58.56ID:FqYYA0QW
例えばこういうことだ。
リンクリストに、
ハンバーガー、りんご、みかん、ドーナツ、パイナップル
の5つを追加したとする。
C、C++、Java、C#では、追加した時に、どこかの5つの変数にこれらの
ポインタを残しておけば、あとから好きなタイミングで、どの
食べ物にも、一瞬でアクセスできる。C、C++では、1クロック。
1番目: ハンバーガー
2番目: りんご
3番目: みかん
4番目: ドーナツ
5番目: パイナップル

3番目のみかんにアクセスするのも、1クロック。
その後に、1番目のハンバーガーにアクセスするのも、1クロック。
その後に、4番目のドーナツにアクセスするのも、1クロック。

例えば、こうだ:
LinkedList ll;
p1 = ll.append("ハンバーガー");
p2 = ll.append("りんご");
p3 = ll.append("みかん");
p4 = ll.append("ドーナツ");
p5 = ll.append("パイナップル");
0416デフォルトの名無しさん垢版2021/11/26(金) 04:03:19.69ID:FqYYA0QW
>>415
[続き]

cout << p3->name; // 1 クロックで3番目のノードのみかんにアクセス。
p3->name="orange"; // 名前を英語に直す。アクセスには1クロックしかかからない。
cout << p1->name; // 1 クロックで1番目のノードのハンバーガーにアクセス。
p1->name="hamburger"; // 名前を英語に直す。アクセスには1クロックしかかからない。
cout << p4->name; // 1 クロックで4番目のノードのドーナツにアクセス。
p4->name="donuts"; // 名前を英語に直す。アクセスには1クロックしかかからない。

書き込みも変更も、アクセスには1クロックずつしか掛からない。
これが、Rustでは借用規則に引っかかるために出来ない。
その結果、標準実装では、k番目のノードに「シーク」する必要があるため、
O(k)や、O(N)の時間が掛かってしまう。
例えば:
cout << seek(ll, 3)->name; // O(N)の時間が掛かる!!
seek(ll, 3)->name="orange"; // O(N)の時間が掛かる!!
0417デフォルトの名無しさん垢版2021/11/26(金) 04:10:09.81ID:r6ugNRE0
>>411
>2. 既に追加したノードを、もう一度アクセスする。
これカーソルでO(1)でできるって何度も言われてるやんけ
書き換え可能なカーソルを複数持つコードを書くのがめんどくさいってならわかるが
0418デフォルトの名無しさん垢版2021/11/26(金) 04:12:10.51ID:FqYYA0QW
>>416
[補足]
cout << aaa;
は、分かりにくいが、aaa の内容を表示する、という意味だと思って欲しい。
他の言語だと、print aaa; と書くことが多い。この点 C++ は異質であることは
認める。
0419デフォルトの名無しさん垢版2021/11/26(金) 04:15:36.11ID:FqYYA0QW
>>417
Rustでは、標準 Cursorでは、読み、書き、削除を出来る参照を同時に持つことは出来ない。
C、C++、Java、C#では、
ll.RemoveAt(p2); // p2 のノードを削除。
もアクセス自体は1クロックで出来るし、今示したコードの好きな場所に
追加しても何の問題も無い。
p2は削除されているからアクセスできなくなるだけで、
他のポインタの値は変更されないので、それ以外は何もしなくても
そのままで良い。
0420デフォルトの名無しさん垢版2021/11/26(金) 04:16:36.76ID:FqYYA0QW
>>417
良く確認してくれ。
RustのCursorは、順番に辿ることはできるが、読み込みと書き込みと削除が
出来るタイプの参照を同時に複数記憶することは出来ない。
0421デフォルトの名無しさん垢版2021/11/26(金) 04:18:59.29ID:r6ugNRE0
>>419
標準(std)のLinkedListならそれはそう

前にも言ったような気がするが、
自前で作って内部構造にunsafecellを使えば、
不変参照を複数持っている状態でも書き換えが可能になる
例えば要素の追加時にそういうことをするカーソルを返せばよい
実装がめんどくさすぎるのは認める
0422デフォルトの名無しさん垢版2021/11/26(金) 04:19:23.54ID:FqYYA0QW
>>420
もっと言えば、C、C++、Java、C#の LinkedListは、
p2 の直後に「じゃがいも」ノードを追加した後、
p4 の直前に「トマト」ノードを追加するなどと言ったことも、
O(1)で出来る。しかも、O(1)と言っても、極限的に速くて、
C、C++の場合は、アクセスには1クロック。

こういうことが、Rustでは、Cursorを使っても出来ない。
0423デフォルトの名無しさん垢版2021/11/26(金) 04:23:10.27ID:FqYYA0QW
>>421
>>257のように、遅くするつもりなのか。
1ノードのアクセスに20〜50クロックくらい掛かるが。
しかも、ダングリングポインタ、つまり、削除後にアクセスしてしまう
減少を防ぐことが出来なくなってるぞ。
0425デフォルトの名無しさん垢版2021/11/26(金) 04:29:37.41ID:FqYYA0QW
>>424
>>257 の実装でもそうだが、まだノードAに対する参照がどこかに残っている状態で、
ノードAの中身を削除できて、ノードAが使っていた要素を新規作成ノードのために
使用されてしまうね。
0426デフォルトの名無しさん垢版2021/11/26(金) 04:42:30.98ID:FqYYA0QW
>>420
[RustのCursorの補足]
・書き込み用のCursorを1個でも作ると、読み込み用のCursorは作れない。

はずだ。難しすぎてちゃんと理解して無いことは認める。
0427デフォルトの名無しさん垢版2021/11/26(金) 04:49:17.40ID:FqYYA0QW
>>421
std::cell::UnsafeCell なるものがあるのか。
Rustの参照は種類が多すぎ。
学んでも学んでもキリが無い。
しかも、1つずつをちゃんと理解するのが難しい。
0428デフォルトの名無しさん垢版2021/11/26(金) 09:55:21.11ID:5+U4u14D
>>404
Pathといってもこちらから使うだけならAsRef<Path>だからStringと&strでも全く問題なくOsStringの存在すら知らなくていい
したがって出てくるのはDirEntryのみとなる
それも周り全てUTF8環境ばかりなのでinto_string()で全てSome(String)になるため結局OsStringを扱ったことは一度もない
0430デフォルトの名無しさん垢版2021/11/26(金) 12:12:39.51ID:Ye0bskEh
>>428
いやいやせっかく標準ライブラリがWindowsでも動くよう苦労してくれてるのにそれを台無しにするなよ
個々のアプリで雑に対処するならともかくRust擁護派がRustの強みを否定してどうする

あと Path::file_name も Option<&OsStr> 返すしこれは利用頻度高い
0431デフォルトの名無しさん垢版2021/11/26(金) 20:45:27.01ID:MbvsChzk
>>430
Rustはちゃんと考えられてるね
ただし自分はWindowsを使うことは100%ないから path.file_name().unwrap().to_str().unwrap() 等でいいし
他にも use std::os::unix::fs::MetadataExt して metadata.uid() 等することもある
0432ハノン ◆QZaw55cn4c 垢版2021/11/26(金) 21:02:52.31ID:xSrpn+m5
>>411
リンクリストや広く一般的なデータ構造の空間的・時間的オーダーを語る場合には
ノードの追加
ノードの検索
すでに取得している指定ノードの削除

あたりを考えるのが普通ですが、

「一度取得したノードの再アクセスコスト」を特に取り上げて考えるというのは、確かに rust の特殊性を示しているものといえそうですね…

>>413
生まれてきてすみません…
0434デフォルトの名無しさん垢版2021/11/27(土) 13:16:38.57ID:Y9o/DNQu
ちゃんと正確に議論されているのに、最後の最後でQZがめちゃくちゃな
ことを言い出す。それが最後に書かれたことによって、このスレに
後から来た人には「まとめ」の様に見えてしまうから、大迷惑。
全くまとめになってない、でたらめなことを書くから。
0435デフォルトの名無しさん垢版2021/11/27(土) 13:19:47.46ID:Y9o/DNQu
ようは、秀才達が集まっているクラスで、一人だけレベルの低い人がいて、
秀才達が大体理解したのに、「まとめ」として、レベルの人が全く
デタラメなことを話す。それがQZ。
クラスの場合、みんなの雰囲気でQZがレベルが低いことが分かるので呆れられ、
無視され、せせら笑いが聞こえるが、ネットだとそれが分からないから困る。
現実世界では言葉にしなくても、ひそひそ場なしや、せせら笑いなどで分かるが
ねっとではそのような言外のコミュニケーションが出来ないから。
0436デフォルトの名無しさん垢版2021/11/27(土) 13:22:32.48ID:Y9o/DNQu
>>435
どうせ、QZは、この文書の誤字脱字を発見して馬鹿にするんだろう。

誤字訂正:
誤:レベルの人が全く
正:レベルの低い人が全く

誤:ひそひそ場なしや
正:ひそひそ話や

誤:ねっとでは
正:ネットでは
0437デフォルトの名無しさん垢版2021/11/27(土) 17:31:40.13ID:v9cw8FEl
4レスも使って成果物も作れない評論家様はそびえ立つクソだからなぁ。

>>432のまとめが嫌なら、中身のない4レスのうち1レスを使ってご立派なまとめぐらい書き込んだら?
0440デフォルトの名無しさん垢版2021/11/27(土) 19:39:40.61ID:SLaQ3CeJ
あわしろ氏はC++は使わないほうが良いと言ってる。
0441デフォルトの名無しさん垢版2021/11/27(土) 20:00:10.09ID:WDqbhltk
C++をあまり使用してなさそうなよくわからないあわしろ氏でなく自分の意見出しなよ
0443デフォルトの名無しさん垢版2021/11/27(土) 21:09:50.54ID:riEP2Tv6
>>434 >>442
お二人方どちらでもいいから
具体的に削除でダングリングが発生しないCかC++のO(1)コードを示してよ
それが示せない限り机上の空論
もしコードが示されれば対応するRustのコードを出します
0445ハノン ◆QZaw55cn4c 垢版2021/11/27(土) 22:11:02.52ID:bCVlBsXA
>>443
>具体的に削除でダングリングが発生しないCかC++のO(1)コードを示してよ

>>432
>「一度取得したノードの再アクセスコスト」を特に取り上げて考える
という、他ではあまり聞いたことのない特殊な話ゆえに筋を深く追えていないのですが、

>>432
>リンクリストや広く一般的なデータ構造の空間的・時間的オーダーを語る
において
@
>すでに取得している指定ノードの削除
でいいですか?
A
データ構造は一方向リストでいいですか?
0447ハノン ◆QZaw55cn4c 垢版2021/11/27(土) 23:03:04.21ID:bCVlBsXA
>>446
それは末尾または冒頭ノードの削除の話ですね
何が与えられていて、何を削除するのか、きちんと定義していただきたいです
0448ハノン ◆QZaw55cn4c 垢版2021/11/27(土) 23:04:36.52ID:bCVlBsXA
>>446
失礼、あるいは特定ノードの上流ノードの探索の話もありますね
確かに双方向の方が楽チンですが、「ダブルポインタ」を使えば単方向でも処理できないわけではないです
0449デフォルトの名無しさん垢版2021/11/27(土) 23:42:34.01ID:+ONNbmgV
スマンが、余り言いたくないことだが、QZが出てくると話がとてもややこしくなる。
0451ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 02:32:25.17ID:DhOI6JvL
>>449
当然でしょう

>>432
>リンクリストや広く一般的なデータ構造の空間的・時間的オーダーを語る場合には
>ノードの追加
>ノードの検索
>すでに取得している指定ノードの削除

>あたりを考えるのが普通

なのに、

>>445
>>「一度取得したノードの再アクセスコスト」を特に取り上げて考える
>という、他ではあまり聞いたことのない特殊な話

を延々とやっていることに噛み付いているのですから

さて実装実装…
0453デフォルトの名無しさん垢版2021/11/28(日) 03:42:41.88ID:sDAG0wCq
ある特定のエントリーを持つ変数はプログラム中に複数存在しうると議論中にも出ていたから
リファレンスカウンタは必須になるな

重要な点としては
コンストラクタやデストラクタやスマートポインタに隠れて曖昧にならないように
それらを使わずに実装すべきだ
そもそもC言語でもO(1)という話なのだから
まずはC言語かつ標準ライブラリのみ使用が今回のコード条件
0454ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 04:07:17.98ID:DhOI6JvL
>>453
ん?アンカーで示してください
今回はリファレンスカウンタは実装に含めないつもりです、まあ C で書くつもりですけど
0455デフォルトの名無しさん垢版2021/11/28(日) 10:45:19.29ID:tHJVymxJ
もうソース出せって意地悪言わないで、無視しときなよ
配列に格納し直すのが彼のアイデアの全てなんだから、つついても面白い話は出てこないよ

O(1)で追加・削除できる配列も作れる!って言い出したら、多分リンクリストを使うってことだよ
0459デフォルトの名無しさん垢版2021/11/28(日) 17:42:46.59ID:4++rc1oJ
>>451
>>432では、あなた、そういうこと書いてなかったよね。
こういう議論でははっきり言わないと分からないよ。

でも、あなたの観点は間違ってる。
C/C++/Java/C# においては、リンクリストで、一度作成したノードのアドレスは
ずっと保存するのが基本で、「先頭からの通し番号」で「辿る」ということは効率
が悪すぎて特殊なケース以外ではしないから。
0460ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 17:47:22.55ID:DhOI6JvL
>>459
もうリンクリストなんか不要で、最初からハッシュテーブル一本でやっていくべきなのでは?
なんでリンクリストとハッシュテーブルを両方使うのですか?
0462デフォルトの名無しさん垢版2021/11/28(日) 17:54:05.88ID:4++rc1oJ
QZは、ポインタが 1 クロックでどんな場所にもたどり着けることを理解出来て無い
のではないか。
アドレスさえ分かっていれば、1クロックであらゆるオブジェクトにたどり着けるぞ。
基本的にハッシュ構造とは全く関係無い。
0463ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 17:58:02.00ID:DhOI6JvL
>>461
失礼、>>444 とは別の方なんですね

でも、

>C/C++/Java/C# においては、リンクリストで、一度作成したノードのアドレスは
>ずっと保存するのが基本で、「先頭からの通し番号」で「辿る」ということは効率
>が悪すぎて特殊なケース以外ではしないから。

それはそうです、リンクリストを頭から舐めるのは効率がイマイチなのはおっしゃるとおり、単純な構造だからそれはしかたがない
しかし、

>リンクリストで、一度作成したノードのアドレスはずっと保存する

って、どこにどういう形で保存するのです?
0464ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 17:59:56.44ID:DhOI6JvL
>>462
>QZは、ポインタが 1 クロックでどんな場所にもたどり着けることを理解出来て無い
>のではないか。
>>456, >>458 で示した程度には理解しているつもりです

>アドレスさえ分かっていれば、1クロックであらゆるオブジェクトにたどり着けるぞ。
で、そのアドレスをどのように管理するのですか?どのような形でどのようなデータ構造に格納するのですか?C/C++ で説明いただくと助かります
0465デフォルトの名無しさん垢版2021/11/28(日) 18:32:54.89ID:Izo/gJUY
>>463
>>リンクリストで、一度作成したノードのアドレスはずっと保存する
>って、どこにどういう形で保存するのです?

・リンクリスト全体のノードを辿ればいい場合には保存する必要が無い。
 なお、その場合、1ノード右側のノードのアドレスを取得するのは1〜2クロック
 しかかからない。

・例えば、1000個のノードが入っている場合の、特定の 2 個のポインタを
 保存したい場合には、グローバル変数の2つのポインタにそれぞれの
 アドレスを代入しておけばよい。
 それは丁度、ArrayList(vector)の場合であれば、添え字番号を2つの整数
 変数に代入しておくのと全く同じこと。

・要は、ノードを識別するための数値が、配列では整数型の添え字番号であったところが、
 リンクリストでは、ポインタ型のアドレスになるというだけのこと。
 決して後者に置いては、通し番号を使ってはいけない。
 数学的には、次のような双対関係の様なものが存在していると考えられる:
 (配列, 添え字) <---> (リンクリスト, アドレス)
 QZを含めて、この双対関係を理解できておらず、
 (配列, 添え字) <---> (リンクリスト, 添え字)
 と間違って理解してしまっている人が多いことから、リンクリストでのランダムアクセス
 が O(N)などと謝った認識に至ってしまう人が多いと考えられる。
 しかし、正しく双対関係を理解すれば、O(1)であることが理解できよう。
0466ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 18:40:36.55ID:DhOI6JvL
>>465
結論から申し上げれば、ここはプログラム板だから、適切なお題を設定してプログラムで例示いただけませんか?

>リンクリストでのランダムアクセス が O(N)などと謝った認識

いいえ、リンクリストの各ノードのアドレスは、リンクリスト内で調達するのならば、O(N) でしか取得できないものですよ
あなたはリンクリスト以外の何か別のデータ構造を使ってリンクリストのアドレスを管理しようとしているようですが、
ならば、もうリンクリストなんか最初から止めちまえばいいのじゃないでしょうか?
0467デフォルトの名無しさん垢版2021/11/28(日) 18:50:25.63ID:Izo/gJUY
>>466
あなたはやはり馬鹿だな。
それをいうなら、配列も同じ。
配列の添え字番号を覚えておくのに、別の配列が必要になる。
お分かりかな?
あなたは、双対を全く理解出来て無い。
0470デフォルトの名無しさん垢版2021/11/28(日) 18:58:57.15ID:uSmUEadq
アドレス保持してればなんでもランダムアクセスできるっていうなら
あらゆるデータ構造がランダムアクセス性を持つということになってしまうな
0471デフォルトの名無しさん垢版2021/11/28(日) 19:16:56.34ID:/zln3poJ
>>466
Qちゃんお疲れ

> あなたはリンクリスト以外の何か別のデータ構造を使って
> リンクリストのアドレスを管理しようとしているようですが、
> ならば、もうリンクリストなんか最初から止めちまえばいいのじゃないでしょうか?

それは色んな人がわりと最初のころから既にツッコミ済みなのだよ…
ようやく議論に追いついたねキミは
0472デフォルトの名無しさん垢版2021/11/28(日) 19:42:21.78ID:1e4/tv+M
>>470
実際、C言語などから高級言語にポインタの概念が入ってからはそうなった。
ただ、Rustはそうなって無いから問題なんだよ。
0473デフォルトの名無しさん垢版2021/11/28(日) 19:42:59.18ID:ZOlCZyFx
>>462
ポインタの指す領域に1クロックでアクセスできるCPUなんてあるんですか?
ポインタの指す先がメモリにあるかキャッシュにあるかで異なりますがL1キャッシュにあっても数クロックかかるのではないかと思います

数クロックを争うような話をするなら実装がないと話にならないと思うので、まずは比較したい書く言語の実装を用意しましょうよ
既存のコードへのリンクで良いので
0474デフォルトの名無しさん垢版2021/11/28(日) 19:43:39.06ID:1e4/tv+M
やっぱり、数学が出来ない人は、双対の概念に脳が追いついてこないらしい。
双対という言葉の意味が分からなくても、生まれつき頭のいい人なら、
俺の言っている意味がわかるはずだ。
0476デフォルトの名無しさん垢版2021/11/28(日) 19:44:50.23ID:ZOlCZyFx
>>472
任意のアドレスへのアクセスは本質的にunsafeだと思うのですが、safe rustでそれができないことにどのような問題があるのですか
0477デフォルトの名無しさん垢版2021/11/28(日) 19:45:41.68ID:ZOlCZyFx
>>475
リンクリストは参照局所性が悪いのでキャッシュに載っていない確率が大きいのですが、本当に高速なのですか?
0478ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 19:59:16.91ID:DhOI6JvL
>>474
双対性にもいろいろありますよね…論理学上の双対命題(∩と∪、∀と∃の入れ替え)ならばその否定が証明できますが、そういう意味ですか?
それとも正十二面体と正二十面体の双対性ですか?
適当にペアにして双対と呼んでいるだけなのでは?
0480ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 20:10:07.08ID:DhOI6JvL
>>473
いや、突っ込みどころはそこではなくて、
「あるときは O(f) ランダウのオミクロンで話をしたかと思うと、次の瞬間、クロック数を問題にする」というバラバラな論理展開でしょう
ランダウでやるんだったら最後までランダウで統一してほしいのですが…
0481デフォルトの名無しさん垢版2021/11/28(日) 20:33:56.21ID:tN4i8A7m
>>480
ランダウ記号は、大まかな分類しか示せない。例えば、
O(N)は、N→∞ の時に、
O(N)/N < α (alpha)
のように有る正の実数αによって、「抑えられる」という意味しか示せないし、
O(1) < α (alpha)
であることしか意味しない。
だから、O(1)であることよりも、1クロックであることの方がずっと意味が強い。
なので、ちゃんと1クロックであると分かっているなら1クロックと書いた方がいい。
0482ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 20:51:47.55ID:DhOI6JvL
>>481
ある数量に対応する空間的・時間的コストの依存状況を滔々と語っていたかと思うと、次の瞬間は実時間に関する話に都合のいいように鞍替えするのは論理的でない、といっているのです
実時間なら実時間、依存関係なら依存関係できっちり話をわけてほしいですね
0483デフォルトの名無しさん垢版2021/11/28(日) 20:59:23.99ID:tN4i8A7m
>>482
悪いが、お前が馬鹿なだけだ。
数学的には、O(1)と書くこともあれば、実クロックで書くこともあり、
混ぜたらいけないなんてことは無い。
ちゃんと理解していれば、混ぜても問題ない。
0484ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 21:06:52.79ID:DhOI6JvL
>>483
「数学的」の定義を伺いたいものですが、それはさておき、実クロックなんて「おま環」な話をしても仕方がない場合も多いのですよ
今はキャッシュのヒット率で処理速度も大きく変わるから、実クロックによる考察なんてほとんど無意味です

しかしデータ数等の「ある数量」に対する時間的・空間的コストの評価ならば、それは、どの環境にもっていっても通用する、すなわち適用範囲が広いのです
何か評価をしたいのなら、広い環境で通用する評価方法の方が有用でしょう

あなたは、その二つの評価方法の意義の違い(「どちらが有意義か」)を知らないから「混ぜたらいけないなんてことはない」などとシレっといえるのですよ
0485デフォルトの名無しさん垢版2021/11/28(日) 21:14:34.22ID:tN4i8A7m
>>484
そうじゃないんだ。実際のクロック数の事ではなくて、マシン語で書いたときに
1命令だということなんだ。
0486デフォルトの名無しさん垢版2021/11/28(日) 21:17:54.80ID:tN4i8A7m
キャッシュの話なんかは状況が複雑すぎて議論を複雑にするだけで、本質を理解する
邪魔になる。
まず、それは横に置いておいて、基本を理解しないといけない。
キャッシュの影響についてはその次。

また、なら、最初から「1命令」と書いておけば良かったのに、という突っ込み
が予想されるが、1命令でも乗算命令なんかは13クロック(レイテンシ)以上かかるから
それとは区別するために1クロックと書いた。
キャッシュは複雑すぎて話が混乱するだけ。
ポインタを介してのアクセスが1〜2クロックなのは、今のx86系だとアーキテクチャに
依存せず必ず言えることだから、そう書いた。
0487ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 21:20:07.26ID:DhOI6JvL
>>485
命令数なんてもっと当てにならないですよ、内部で別形態に変換され並列に実行されたりするわけで、人手で最適化することは不可能なしろもの
そんな制御できないものを評価対象にしてもしかたがないのでは?
0488ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 21:25:24.33ID:DhOI6JvL
>>486
>ポインタを介してのアクセスが1〜2クロックなのは、今のx86系だとアーキテクチャに
>依存せず必ず言えることだから、そう書いた。

残念ですがキャッシュにヒットするかしないかで大きく実行時間は変わりますね、キャッシュにヒットせず、RAM 空間上から引っ張ってくる場合は数十クロックは必要でしょうね…
そんな「お前の環境でしか通用しない話だろう」的な曖昧な評価方法よりも、どの環境でも通用するランダウのO記号による評価の方が有意義でしょう

どちらの方が有効範囲が広い有意義な評価法なのかを知らないから、ちゃんぽんにして話をしても不自然さを感じないじゃないですか、あなたは?
0489デフォルトの名無しさん垢版2021/11/28(日) 21:26:27.36ID:tN4i8A7m
>>487
そうでなくて、Rustでも、O(1)というものだけなら、作ろうと思えば作れるから
1クロックと書かざるを得なくなったんだよ。
Rustの場合は、O(1)でも、単なるポインタでは無く、配列を介すので、
乗算、足し算、境界チェックが入ってしまうのでトータルで20〜50クロック
くらい掛かる。このうち、境界チェックだけは外せるかも知れないが。
0491ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 21:30:30.36ID:DhOI6JvL
>>489
>乗算、足し算、境界チェックが入ってしまう

C/C++ の配列とても乗算・足し算は入りますよ…
そんな瑣末な話とO(1), O(N) の話をちゃんぽんにしても不自然さを感じない感性に私は大いに疑問を感じます
0492ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 21:34:48.65ID:DhOI6JvL
>>490
よくご存知ですね…
まあ、今日は基本的なデータ構造を基本的な言語を使用して白紙からコーディングする機会を下さったあなたには感謝してますよ、久々に脳細胞を使ったのでちょっといい気分です
0493デフォルトの名無しさん垢版2021/11/28(日) 21:40:43.94ID:tN4i8A7m
Cの場合のリンクリストのポインタを介してのアクセスは、
mov ebx,ptr
mov eax,[ebx]
ので済む。配列の場合は、
mov ebx,index ;添え字番号
mov eax,[ebp+ebx+32]   ;32はスタックの中での位置
だから、配列とポインタで速度が変わらない。むしろこの例だとリンクリスト
の方が僅かに速いくらい。

Rustの場合、借用規則で禁止されてしまうため、以下のようになってしまう。
このスレである人が実装を示した独自Cursorをrustcでマシン語に直したものを
アセンブリ言語で書いた場合、次のように成る:
mov ebx,pseudo_ptr ;Cursorの中味はポインタの変わりに配列の番号になってしまう。
cmp ebx,配列要素数 ;safeモードの配列の境界チェック(これと次の命令はオプションで外せるかも)
jae 境界チェックエラーのラベル ;条件ジャンプ命令は遅くなる原因になりやすい。
imul ebx,要素のバイト数 ;13〜35クロック位。CPUによってこの限りではない。
add ebx,配列の先頭アドレス ;Cursorの実装の内部で用いられていた配列の先頭アドレス
mov eax,[ebx] ;間接アドレッシングによって実際にアドレスebxにアクセスする。

これは、O(1)ではあるが、20〜50クロック位かかり、先に示したCの場合とは
雲泥の差である。
0494デフォルトの名無しさん垢版2021/11/28(日) 21:42:26.92ID:8j2GjV45
俺は Rust 書けない C++ マンだけど、双方向リンクリストのサンプルコードを書いてみた。
Rust で insert, remove 操作を O(1) で実装可能かどうかが論点ですよね?
リストの要素数に関わらず insert, remove 操作を固定計算量で実行可能であればそれは O(1) です。

https://wandbox.org/permlink/AHWR4LIjkMCvWuZE

insert, remove 実装のコードだけここに貼ります。全てのコードは上記で確認願います。

--------------------------------
node *insert(node *target, int value) // ノードを target の直後へ挿入
{
 node *n = new node;
 n->value = value;
 n->prev = target;
 n->next = (target != nullptr) ? target->next : nullptr;

 if (n->prev != nullptr) n->prev->next = n;
 if (n->next != nullptr) n->next->prev = n;
 if (head == nullptr) head = n;
 if (tail == target) tail = n;

 return n;
}
void remove(node *n) // 指定ノードを削除
{
 if (n->next != nullptr) n->next->prev = n->prev;
 if (n->prev != nullptr) n->prev->next = n->next;
 delete n;
}
0495デフォルトの名無しさん垢版2021/11/28(日) 21:43:21.57ID:tN4i8A7m
>>491
お前はアホか。
リンクリストの場合は、乗算が入らないんだよ。

>>493
ミス訂正:
配列の場合は、
mov ebx,index ;添え字番号
imul ebx,配列のバイト数
mov eax,[ebp+ebx+32]   ;32はスタックの中での位置

従って、リンクリストの方が一般的にはアクセスが速い。
リンクリストは、1クロック位、配列の場合は、要素が一般のバイト数の場合は、
14〜36クロック位。
0496デフォルトの名無しさん垢版2021/11/28(日) 21:47:47.53ID:tN4i8A7m
>>494
>Rust で insert, remove 操作を O(1) で実装可能かどうかが論点ですよね?
そうじゃない。
Rustでも、insert, remove 自体は、標準実装でも O(1)で行える。
ところが、アクセスが、標準実装では、借用規則のために複数の
読み書きポインタを永続的に保持することが出来ないので、ノードの位置を
先頭からの通し番号で覚えておいて、アクセスするたびに毎回先頭から
辿る必要があるため、O(N)かかる。

特殊な独自実装をすると、アクセスがオーダー的にはO(1)で出来るが、
特殊実装な故に、>>493 の後半のようになってしまい、
20〜50クロック位かかる。
0497ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 21:49:24.66ID:DhOI6JvL
>>494
読みました
私の場合は双方向リストを循環させ、始点のみをポイントすることとしましたが、結果として記述はあまり簡単にはならなかったですね、うーむ
0498デフォルトの名無しさん垢版2021/11/28(日) 21:56:03.25ID:tN4i8A7m
すまんが、馬鹿に何言っても理解されない。
疲れるだけだということが分かった。
0499デフォルトの名無しさん垢版2021/11/28(日) 21:56:11.42ID:tN4i8A7m
すまんが、馬鹿に何言っても理解されない。
疲れるだけだということが分かった。
0500デフォルトの名無しさん垢版2021/11/28(日) 21:56:13.54ID:tN4i8A7m
すまんが、馬鹿に何言っても理解されない。
疲れるだけだということが分かった。
0501デフォルトの名無しさん垢版2021/11/28(日) 21:57:51.47ID:8j2GjV45
remove メソッドにバグがあった (head, tail を更新していなかった) ので一応修正。
https://wandbox.org/permlink/GlDCsezlcix3aJvi

>>496
なるほど。アクセス時に通し番号的な物が必要になるのであれば
insert, remove 操作時にもその通し番号を振り直す必要があるので、O(1) では実現できない気がします。

>>497
双方向リンクリストは始点と終了をペアで持つという固定観念があったので、その発想はなかったです。
0502デフォルトの名無しさん垢版2021/11/28(日) 22:02:54.87ID:tN4i8A7m
>>501
>なるほど。アクセス時に通し番号的な物が必要になるのであれば
>insert, remove 操作時にもその通し番号を振り直す必要があるので、O(1) では実現できない気がします。
先頭や末尾では無い途中のinsert、removeであれば、あなたの言うとおり。
追加する直前のノードにたどり付くまでに一般的にはO(N)の時間が掛かる。
ただまあ、末尾追加や先頭追加と、末尾削除、先頭削除なら、RustでもO(1)で
出来るだろう。
なお、Cursorを使えば、よくあるケースだけは高速に行えるようになっているかも知れないが。
あくまでも良くあるケースだけは、unsafeを使って特別対応しているだけ。
複雑な一般的なケースでは、やはり、O(N)かかってしまう。
その意味で、あなたの言っていることは正しい。
0504デフォルトの名無しさん垢版2021/11/28(日) 22:17:12.75ID:tN4i8A7m
>>503
こだわっているというか、あれは、オーダー的にはCと同じく、ほとんど全ての
動作をO(1)で出来てしまうリンクトリストをRustでも出来ているから、
注目に値する。
ただし、O(1)と言っても、実際には遅い。
また、Read After Delete、ダングリングポインタに相当するものがRustでも
生じる。たとえ、safeモードで書いても。
0507デフォルトの名無しさん垢版2021/11/28(日) 22:26:36.40ID:tN4i8A7m
>>505
Rustはそれを売りにしてるからだよ。
C/C++は最初から諦めてる。

>>506
その指摘は正しい。
平均的にはO(1)だが、スパイク状に(不定期に)O(N)のコピー動作が入ってしまう。
0508ハノン ◆QZaw55cn4c 垢版2021/11/28(日) 22:29:15.25ID:DhOI6JvL
>>501
私のやり方でよかったことは、prev/next の無矛盾性のチェックが簡単に書けることくらいでした、他は複雑になってしまった…
0509デフォルトの名無しさん垢版2021/11/28(日) 22:50:50.98ID:qezuw3R9
>>507
売りにしてるいうても結構厳しい制限だからデータ構造に直結するようなコードはsafeのみじゃ無茶だぞ
連結リストのようにユーザ側もダングリングとか多重参照とか気をつけなきゃいけないタイプのものは、
safeの範囲じゃ回りくどいことやるハメになるか、そもそも本当に無理になるかだ
0510デフォルトの名無しさん垢版2021/11/28(日) 22:53:17.54ID:Z9Xk/5kf
>>496
>ところが、アクセスが、標準実装では、借用規則のために複数の
>読み書きポインタを永続的に保持することが出来ないので、ノードの位置を
>先頭からの通し番号で覚えておいて、アクセスするたびに毎回先頭から
>辿る必要があるため、O(N)かかる。

そうなんだ
でもこれってC/C++でもメモリ安全で、スレッドセーフとかにしたら同じにならん?
0511デフォルトの名無しさん垢版2021/11/28(日) 22:59:54.62ID:hrke4Ba5
自分はがんばって数学の勉強をしてきたので自分の考えは絶対に正しい、間違うはずがないと思いこむ。
そうなると一度間違った考え(リンクドリストの任意の要素にO(1)でアクセスできる)を持ってもそれを間違った考えとは気づかずにその間違いを補強するようなチグハグな考え方をするようになる。
反ワクチンのようなトンデモ科学にはまっちゃう人に周囲の人がいくら正しい科学知識で説得しても自分の考えに疑問を持つどころか、自分の考えは絶対に正しい、周りのやつらは頭がおかしいと思いこんでしまう。

自分の考えが間違うこともあるのではないかと謙虚になることも重要だということだね。
0512デフォルトの名無しさん垢版2021/11/28(日) 23:00:17.08ID:j8Nrs0jp
まずポインタで持てば1クロックは明らかに嘘
今後はクロックという言葉を使うのはやめなさい

次にポインタで持てばリンクリストはO(1)も明らかにおかしい
例えばハッシュテーブルもバイナリツリーもO(1)になってしまう
0513デフォルトの名無しさん垢版2021/11/28(日) 23:03:08.30ID:tN4i8A7m
>>510
Cの場合、リンクリストは経験的に言えば、簡単に扱えるので結構安全。
すっきり分かり易いので安全になる。動作が素直だし。

むしろ、途中削除、途中挿入した場合、配列の方が扱いが難しい。
リンクリストは他のノードのアドレスが変わらないのでポインタの値は
変化させなくて良いが、配列の場合は操作をしたノードより後ろに
有るノードの添え字番号がずれてしまうため、そのたびに
管理番号を付け替えるようなことが必要になってしまい、
データ構造が複雑な時に管理がとても大変になる。
リンクリストだとそのような手間が要らないので便利。

ただし、(配列, 添え字) <--> (リンクリスト, アドレス) の双対関係
は常に念頭に置いておく必要がある。後者は基本的には決して
添え字(通し番号)を使ってはいけない。なぜなら、それは後者においては、
ID値としては使えないから。

ただそもそも配列は、添え字はID値としては不十分というか、配列には絶対不変の
ID値が存在しない。リンクリストはアドレスが絶対不変のID値として使える。
0514デフォルトの名無しさん垢版2021/11/28(日) 23:04:35.17ID:tN4i8A7m
>>511 >>512
まずは、
(配列, 添え字) <--> (リンクリスト, アドレス)
の双対関係を理解しよう。

これが理解出来て無い人は、リンクリストの本来の性能も、本来の使い方も
出来ない。
0517デフォルトの名無しさん垢版2021/11/28(日) 23:08:15.36ID:j8Nrs0jp
じゃあハッシュテーブルもエントリーアドレスでアクセスできるからO(1)と言い出す気か?
0518デフォルトの名無しさん垢版2021/11/28(日) 23:11:15.41ID:tN4i8A7m
>>514
[補足]
要は、「配列の世界」と「リンクリストの世界」では、世界自体が別物なので、
要素/ノードを識別する手段も違い、前者は添え字番号、後者はアドレスが基本量となる。
従って、リンクリストでは、ノードを識別するには、必ずアドレスを使うことが基本。
それが最も自然であり、高速であるから。
いつまでも、添え字番号で識別する方法しか理解できない人には、言っている意味が理解できない
だろう。

電気と磁気にもさまざまな双対関係がある。世界がある種の対称になっているから、
その際に、正確に対応する量を入れ替えてやら無ければならない。リンクリストでは
通し番号ではなくアドレスを使う。
そうしないと公平ではない。
0520デフォルトの名無しさん垢版2021/11/28(日) 23:13:05.79ID:tN4i8A7m
>>517
はあ?
ハッシュテーブルは、実質的にO(1)にとても近い速度で検索できるから
使われているんだが。
0521デフォルトの名無しさん垢版2021/11/28(日) 23:16:38.50ID:sDAG0wCq
>>514
それは嘘だと誰でもわかる
リンクリストの個別要素のアドレスに対応するものは配列の個別要素のアドレスでありハッシュマップの個別要素のアドレスである
そしてアドレスを持てばO(1)とトンデモを言い出すならば全てのデータ構造がO(1)となる
つまりリンクリストのO(1)は嘘
0522デフォルトの名無しさん垢版2021/11/28(日) 23:18:09.73ID:Z9Xk/5kf
>>513
>Cの場合、リンクリストは経験的に言えば、簡単に扱えるので結構安全。
>すっきり分かり易いので安全になる。動作が素直だし。

そんなに簡単だとかいうなら、試しに実装を見せてほし・・・
0523デフォルトの名無しさん垢版2021/11/28(日) 23:25:05.70ID:tN4i8A7m
>>521
お前が生徒だったら0点つけてやる。

そもそも、動的配列は要素数が内部容量を超える時にアドレスが時々変わって
しまうから、ID番号として基本的にアドレスは使えない。
それをすると、末尾追加するだけでも、定期的にID番号が変わってしまうので
その際にID番号として使っているアドレスを全部修正しないといけなくなるから。
しかし、アプリ内のID番号を全部修正するのは、効率免で良くない。
だから、配列だと要素の一番ましなID番号は添え字番号。

一方、リンクリストで最も効率の良いID番号は、アドレス。
しかも、リンクリストの場合、任意の場所への挿入、任意のノードの削除を
行っても、他のノードのアドレスは変わらないので、アドレスをID番号
として用いている限り、どんな操作をしてもID番号の修正が不要となる。
こんなによいID番号はないわけで、敢えて添え字番号をID番号に使うのは
不適切。
0524デフォルトの名無しさん垢版2021/11/28(日) 23:26:21.97ID:tN4i8A7m
>>522
Cの入門書で、リンクリストについて書いてあるもの読んで理解して、
頭が悪くなければ、そう自然に解釈できる。
根本的に馬鹿な人には無理かも。
0526デフォルトの名無しさん垢版2021/11/28(日) 23:43:54.48ID:tN4i8A7m
>>525
Cでは生ポインタ一個に対して、Rustは参照関連だけでも、20種類は下らないほど
色々な複雑な仕組みがあるのは、全て safe のためであるのに、safeでなくなったら
それこそCの圧勝になるが。
0527デフォルトの名無しさん垢版2021/11/28(日) 23:48:12.68ID:qezuw3R9
>>526
コーディングはゲロのようにめんどくさくなるが、
速度面では別にCにそう負けるもんではない
多分最適化しきれなくてほんのちょっと遅くなる部分はありそうだが
0528デフォルトの名無しさん垢版2021/11/28(日) 23:48:45.22ID:tN4i8A7m
>>477
それは、実はリンクリストも十分に局所性が有る。
というのは、追加するときには、リンクリスト全体のごく一部にバースト的に
挿入することが多いからだ。
そしてその時、ノードのアドレスは等間隔に並ぶ傾向が有るから。
0530デフォルトの名無しさん垢版2021/11/28(日) 23:51:28.85ID:qezuw3R9
>>529
今回の例が何のことか把握してないが(QZが絡んでいるレスは読みづらすぎる)、
配列がどうたらとかの話なら別に配列なんていらんよ
0531デフォルトの名無しさん垢版2021/11/28(日) 23:52:03.44ID:j8Nrs0jp
結局この全員の合意とは無関係な些末な話ばかりだな

>まとめ
>・C/C++で記述できることは同じ安全度合いで常にRustでも記述できる
>・そのうちほとんどのケースではRustだとメモリ安全性を保証する形で記述できる
>・つまり言語としてC/C++よりもRustの方が優れている
0534デフォルトの名無しさん垢版2021/11/28(日) 23:58:27.96ID:qezuw3R9
極論だけど各メンバをUnsafeCellにしてunsafe使いまくれば、
shared XOR mutableルールぶち破れるから、
C/C++でできることはコーディングめんどくさくなるし安全性が結構悲しいことになるけど(でもCとかと同程度)
Rustでも不可能ってことはない

なんならCコードをRustコードに自動変換するやつすらあったような
成熟度は知らんが
0536デフォルトの名無しさん垢版2021/11/29(月) 00:02:50.56ID:g6qk7DwE
>>507
>Rustはそれを売りにしてるからだよ。
>C/C++は最初から諦めてる。

自分で C/C++ は安全じゃないから、って書いてるじゃん
それが結論でしょ
同じ安全性にしたら、同じになるだろ
0538デフォルトの名無しさん垢版2021/11/29(月) 00:15:16.20ID:uM27l7Qv
前から別の人が指摘しているけど、
リンクドリストとは別に配列を用意してリンクドリストの要素へのアドレスを保持するからリンクドリストの任意の要素にはO(1)でアクセスできる
と主張しているが
そのリンクドリストに追加または削除するたびに配列の要素も追加か削除しないといけなくなる。
リンクドリストの任意の位置に追加/削除するのはO(1)だけど、配列の任意の位置に要素を追加/削除するのはO(1)じゃない。
だからリンクドリストと配列を組み合わせて使うとリンクドリストのメリット(任意の位置への追加/削除がO(1))が無くなってしまう。

その配列に静的配列を使うならリンクドリストの最大サイズを予想してあらかじめ大きな配列を用意しないといけない。
動的配列を使うな要素を追加したときにときどきヒープの再確保がおきる。
0539デフォルトの名無しさん垢版2021/11/29(月) 00:21:59.31ID:uYqg1Oz6
>>528
実際のメモリレイアウトがどうなるかは言語処理系のランタイムやlibcに依存すると思うのですが
例えばどの言語のどの処理系のどのランタイムを使使えばそうなることが確認されているのですか
0542デフォルトの名無しさん垢版2021/11/29(月) 00:30:08.36ID:4MgUQE5v
>>534
Rustはもっと単純
生ポインタを使えばC言語と全く同じ状態となる
fn main() {
 let mut a: i32 = 123;
 let raw_pointer = &mut a as *mut i32; // aの生ポインタを得る (unsafe不要)
 let b = &a; // bがaの参照を借用
 // a = 456; // これは借用ルールによりコンパイルエラーとなり書き換えできない
 unsafe { *raw_pointer = 456; } // 生ポインタを使えば自由自在に書き換え可能
 assert_eq!(a, 456); // 借用ルールを逸脱して書き換わっている
 assert_eq!(*b, 456); // 借用している参照bから見ても当然書き換わっている
}

じゃあUnsafeCellなどはいつ使うの?と思うだろうけど
それはRustで安全な型を提供するための部品として用いる
例えばRefCellやOnceCellなどの安全な型は部品としてUnsafeCellを用いている
0543デフォルトの名無しさん垢版2021/11/29(月) 00:39:59.63ID:zo5XubVi
>>541
最初の初期化時に(あまりフラグメンテーションが発生していない状態で)複数要素追加する以外に追加がほとんど発生しないっていう前提ならそうかもね
でも一般にそうじゃないから連結リスト使うんじゃないの?
0545デフォルトの名無しさん垢版2021/11/29(月) 00:45:55.70ID:DszBoyLu
あわしろ氏もC++は危険と言ってる。
0546デフォルトの名無しさん垢版2021/11/29(月) 00:55:31.86ID:27e/xIh/
>>541
参照局所性高めたいなら個々の要素ごとにmallocするのではなくarena的に割り当てすべきなのでは
>>543の言うとおり、フラグメンテーション発生してると何も保証できなくなる
0547デフォルトの名無しさん垢版2021/11/29(月) 00:59:52.29ID:4MgUQE5v
>>542でコードを示したように
C/C++で記述できることは同じ安全度合いで常にRustでも記述できる
したがって以下の合意事項は正しい

>まとめ
>・C/C++で記述できることは同じ安全度合いで常にRustでも記述できる
>・そのうちほとんどのケースではRustだとメモリ安全性を保証する形で記述できる
>・つまり言語としてC/C++よりもRustの方が優れている
0548デフォルトの名無しさん垢版2021/11/29(月) 01:00:10.18ID:HgRvzIV4
しかし、配列の場合は、内部バッファのサイズが拡張される時には全コピーが
発生するから、キャッシュが大規模に乱れてしまうがな。
その点、リンクリストは乱れたとしてもそこまででは無い。
0549デフォルトの名無しさん垢版2021/11/29(月) 01:03:19.07ID:HgRvzIV4
>>547
unsafe付けたら全体の安全性も失われるが。
メモリーの間違いには局所性がなくて原因箇所が分かりにくいからこそ、
Rustはメモリー安全に固執しているんだが。
逆にCはそもそもそれをユニットテストなどで徐々にテストしながら開発を進める
ことで確保する方針を採っている。
0550デフォルトの名無しさん垢版2021/11/29(月) 01:10:35.89ID:HgRvzIV4
リンクリストでのキャッシュの乱れと言っても、アドレスが大幅に異なるものが入り混じっても、
必ずしもペナルティーが増えるわけでは無いぞ。
例えば、2つの大幅にアドレスが異なるノードを交互にアクセスする程度では
キャッシュの読み込み直しは通常の連続アドレスにアクセスした場合に比べて
特に追加発生はしない。
キャッシュメモリ1種類の連続メモリブロックしか収められないわけでは無いからな。
限界はあるが、いくつかのメモリブロックなら同時に収めることが出来るからな。
0551デフォルトの名無しさん垢版2021/11/29(月) 01:12:27.10ID:HgRvzIV4
>>550
逆にキャッシュ制御せずにmemcpy()みたいなもので大きなメモリーをコピーした
場合、キャッシュが全フラッシュしてしまう可能性も有る。
動的配列の場合はそこに注意が必要。
0552デフォルトの名無しさん垢版2021/11/29(月) 01:17:45.41ID:HgRvzIV4
>>550
図を書いておこう。2つのメモリー領域A, B があったとして、
リンクリストが
AAAAAAAAAAA
の状態の途中にノードを5つ追加して、
AAAAABBBBBAAAAAA
のようになっていてもそれほどキャッシュミスは起きない。

さらに、もし、
AABCBBACDBBAABBDBCCC
みたいになっている程度でも、そんなにキャッシュミスは起きない。
なぜなら、A,B,C,D の4箇所くらいならキャッシュにどれも収まるから。
0553デフォルトの名無しさん垢版2021/11/29(月) 01:20:38.16ID:tPktcSTu
>>549
それはウソ
Rustは標準ライブラリの内部に至るところに多数のunsafeがあるのは事実だが
それにより全体の安全性に影響を与えることはない形でのみ提供している

まずunsafeの使用方法は大きく2つに分けられる
(1)影響が局所的に限定される場合
(2)影響が大域的に起き得る場合
つまりunsafeを用いたRustの様々な型やその操作インタフェース等は(1)が満たされている

つまりそれらを利用するプログラムには内部がどう実装されていようと影響をもたらさない
したがってRustのプログラム自体がコンパイラによって安全性を保証することが可能となっている
0554デフォルトの名無しさん垢版2021/11/29(月) 01:21:24.40ID:zo5XubVi
ベンチも取らずにキャッシュヒット率の話するの時間の無駄すぎない?
あとVecに対するLinkedListの優位性の話されても誰もそんなことは問題にしてないぞ?
0555デフォルトの名無しさん垢版2021/11/29(月) 01:26:01.98ID:HgRvzIV4
>>553
それはそうかもしれないが、リンクリストの場合、ノードの識別に
アドレスを使うのが、双対原理によって標準なので、その標準手法を
Rustで使おうとすると、unsafeをアプリ本体で使う必要が出てくる。
つまり、ライブラリの中にunsafeを閉じ込めることが不可能。
これは間違いないはずで譲れない。
0556デフォルトの名無しさん垢版2021/11/29(月) 01:26:35.85ID:tPktcSTu
>>554
ほとんどのケースではLinkedListよりもVecを用いた方が有利
だから使用する言語に関わらず特殊なケースを除けばリンクリストではなくベクターが使われている
0557デフォルトの名無しさん垢版2021/11/29(月) 01:32:54.07ID:HgRvzIV4
>>556
それが間違いなんだって。
そんな思想だから、ChromeではHTMLもtextareaへの文字列の末尾追加ですら遅いんだな。
計算量が理解出来て無い。
VisualStudioも異常に遅いし。
それに比べて日本人の作るVzEditor, WzEditor は速い。
それはなぜかというと、LinkedListも使っているから。
0558デフォルトの名無しさん垢版2021/11/29(月) 01:44:20.89ID:DszBoyLu
LinusもC++は糞言語と言ってる。
0560デフォルトの名無しさん垢版2021/11/29(月) 01:47:20.54ID:DszBoyLu
システムコールの実装によるのでは?
0561デフォルトの名無しさん垢版2021/11/29(月) 01:50:31.36ID:HgRvzIV4
>>559
Push Front を見たら圧倒的に list が速い。
それにC++のライブラリの list はへたくそな実装になっている。
0562デフォルトの名無しさん垢版2021/11/29(月) 01:52:56.70ID:27e/xIh/
>>561
deque無視しないでよ
先頭への追加削除が高速なvectorだよ
クラフをログスケールにするとわかるけどlistより速い
0563デフォルトの名無しさん垢版2021/11/29(月) 01:53:14.65ID:HgRvzIV4
沢山実験して、LinkedListの方が性能がいいことが分かってるからLinkedList
を使ってる。
ベンチマークは、ベンチマークを作る人が正しく理解してなければ、正しい
テストプログラムを書けないから、正しい結果が出ない。
CPUのベンチマークも実際の体感速度に比例しているとは限らないのと同様。
0564デフォルトの名無しさん垢版2021/11/29(月) 01:54:51.63ID:HgRvzIV4
list の実装の仕方や使い方に問題があるだけだ。
何度も言ってるように、listは、双対原理から言って、添え字番号ではなく
アドレスを用いなければ成らないことをベンチマークプログラムを作ってる
人が理解出来て無いから、遅く出てることが多い。
0566デフォルトの名無しさん垢版2021/11/29(月) 01:57:29.30ID:tPktcSTu
>>557
ついにGoogleとMicrosoftを批判しだしたのか

>>561
C++擁護派なのにC++のライブラリまで批判しだしたのか

君が間違っているとは考えないのね?
0567デフォルトの名無しさん垢版2021/11/29(月) 02:04:18.84ID:HgRvzIV4
>>565
要素サイズが128バイトや4096バイトの時には、listの方がvectorより速い。

それに、NonTrivialの時こそ list が効率がいいはずなのに結果が逆になって
いたり、listは、安定なはずなのに、trivial 128 で list のグラフが
途中で直線になってないこともおかしい。
listは、どんなときでも速度が変化しにくい性質があるはず。
何かそのテストはおかしい。
0569デフォルトの名無しさん垢版2021/11/29(月) 02:07:29.41ID:HgRvzIV4
実際に自分で実験したこそが無いのに、誰かが実験したものを信じるな。
実際に一般的なケースでは、vectorとlistでは、listの方が速いことが多い。
0570デフォルトの名無しさん垢版2021/11/29(月) 02:09:04.94ID:tPktcSTu
>>569
ほとんどの用途でベクターが速い
だからほとんどのケースではリンクリストではなくベクターが使われている
0571デフォルトの名無しさん垢版2021/11/29(月) 02:12:28.28ID:HgRvzIV4
>>570
数理に弱いアメリカ人。
だから、VisualStudioも激オソなんだな。
アメリカ人の作るものは何でもでかくて速度が遅い。
車もでかくて燃費が悪い。
0572デフォルトの名無しさん垢版2021/11/29(月) 02:15:22.14ID:27e/xIh/
>>567
NonTrivialはMovableな要素だから追加削除時には要素あたりポインタ数個分のデータがコピーされるだけで小サイズと同じ特性になるのは不思議ではないのでは

listについては要素サイズの変化に対して他のコンテナよりも安定的に見えるけど
さすがに要素のコピー分のコストはかかるから要素サイズ変わっても全く同じという訳ではないけど
0573デフォルトの名無しさん垢版2021/11/29(月) 02:21:21.41ID:HgRvzIV4
こういうベンチマークには、ファクトチェックが必要だ。
今までネットのこういう変な結果のベンチマークを見てきたが、
ソースを見てみると変なことをしてることが多かった。
多かったというより、結果がおかしいと思って調べてみたら全て変なことしてた。
秀才以外が行ったベンチマークは信用できない。
まだ、雑誌は信用できることが多いが、ネットのベンチマークはおかしい。
0574デフォルトの名無しさん垢版2021/11/29(月) 02:23:11.00ID:tPktcSTu
『リンクリスト vs. ベクター』のスレ立ててそこでやったら?
少なくともこのスレでやることではない
0577デフォルトの名無しさん垢版2021/11/29(月) 02:44:22.88ID:HgRvzIV4
作業時間が発生するものを持ち込まないで欲しい。
こっちはボランティアに馬鹿に説明してやってるだけなんだから。
ソースを出せ、と言ってくるのは抽象的理解が出来ないから。
とても簡単なことを言ってるだけなのに、少しでも抽象的(symbolic)
な言葉で語ると全然理解できない。
数学とは抽象性(symbolic)な学問であるから、数学が出来ない人は
コードを示さないと理解できないらしい。
0578デフォルトの名無しさん垢版2021/11/29(月) 02:59:57.67ID:qK4xTYr2
ベンチマークとかはどうでもいいが、
CだろうがRustだろうが実装可能って話にしか見えん
0579デフォルトの名無しさん垢版2021/11/29(月) 07:57:57.28ID:cydEy5/m
>>538
これな。
結局のところ実体へのポインタの配列であればリンクトリストになってなくても話は同じなんじゃないかな。
0580デフォルトの名無しさん垢版2021/11/29(月) 08:02:08.66ID:LzdsKRCS
実体へのポインタの配列だけでいいよなw
それで実体にはすべて到達できるもんw
ある実体の次も、前も、それも両方分かるしw
0582デフォルトの名無しさん垢版2021/11/29(月) 11:26:03.41ID:ynhRtjt2
>>579
違う。
リンクトリスト + 配列だと >>538 が指摘している現象が生じてしまうが、
リンクトリスト + リンクリスト だと生じない。

こういっても、数学力の無い人は理解できないだろうな。
数学力は数学という学問だけの能力ではなくて、脳内のワーキングエリアや
イマジネーションなどに関係しているから、生まれつきの影響が大きい。
0583デフォルトの名無しさん垢版2021/11/29(月) 11:29:51.75ID:ynhRtjt2
>>582
[補足]
抽象的理解が難しい人に具体的に書いておいてやろう。
LinkedList ll;
ArrayList al; //自動伸張方式の動的配列だと仮定する
al[0] = ll.append("りんご");
al[1] = ll.append("みかん");
al[2] = ll.append("バナナ");
だと >>538 が指摘しているような不具合が起きる。しかし、
LinkedList ll;
LinkedList ll2;
ll2.append( ll.append("りんご") );
ll2.append( ll.append("みかん") );
ll2.append( ll.append("バナナ") );
だと起きない。
0584デフォルトの名無しさん垢版2021/11/29(月) 11:36:08.77ID:27e/xIh/
>>583
中身が同じリストを二個用意しても意味がないのでもう少し実践的な例の方が理解のためにはよろしいのでは
スキップリストみたいな構造とは違うのですか?
0585デフォルトの名無しさん垢版2021/11/29(月) 11:36:25.33ID:ynhRtjt2
>>583
もっと具体的に書いてやろう。
リンクリストの中の追加した6つの果物の内、4つを他の配列やリンクリストの
中から参照する例を示しておこう。
これの応用としてリンクリスト内の1000個の品物の内、何らかの条件で選び取った10個を
別の配列やリンクリストから参照することが出来る。

1. リンクリスト + 配列
LinkedList ll;
ArrayList al; //自動伸張方式の動的配列だと仮定する
al[0] = ll.append("りんご");
ll.append("みかん");
al[1] = ll.append("バナナ");
ll.append("すいか");
al[2] = ll.append("パイナップル");
al[3] = ll.append("ブドウ");

2. リンクリスト + リンクリスト
LinkedList ll;
LinkedList ll2;
ll2.append( ll.append("りんご") );
ll.append("みかん");
ll2.append( ll.append("バナナ") );
ll.append("すいか");
ll2.append( ll.append("パイナップル") );
ll2.append( ll.append("ブドウ") );
0587デフォルトの名無しさん垢版2021/11/29(月) 11:39:40.44ID:ynhRtjt2
>>585
これがどういう時に起きるかといえば、最初に1000個の品物の入った
リンクリスト ll がある時、条件に合う品物を1つ探してリンクリスト ll2
の末尾に参照を追加する。
それを10回繰り返した後に、実質的に生じる。
0588デフォルトの名無しさん垢版2021/11/29(月) 12:08:42.24ID:27e/xIh/
>>587
queryに対する抽出結果をリストとして保持しておいて元のリストの更新に応じてquery結果も適宜更新されるイメージですか?
0591デフォルトの名無しさん垢版2021/11/29(月) 12:42:23.24ID:G+erg93y
>>590
正確にはll2のサイズN_ll2の半分に近づくね。
ll2のサイズが大きくなるなら、大きめに初期化するのが無難。スカスカならバランス木のmapかね。
0592デフォルトの名無しさん垢版2021/11/29(月) 12:43:56.81ID:4MgUQE5v
リンクリストを少し調べたところ様々な種類のものが使われているようで
様々な分類が生じるうち今回関係するノードの参照については以下の4種類あるようだ

(A) データを挿入しても作られたノード自体は返さない方式
実際にこの仕様でも困らない用途も多いようでこの方式も普通に使われている
もちろん問題は何も生じない

(B) データを挿入して作られたノードのポインタを直接返す方式
これは危険で最も推奨されない方式
ポインタを握っていても使う時にそのノードは削除されているかもしれない
削除で開放されてヒープに戻され更に再利用されているとデータの中身もnext辿りも滅茶苦茶になりうる
そしてデータの扱い次第で実際に削除は起き得るしUI人間や通信相手から発動ルーチンでの削除も有り得る

(C) データを挿入して作られたノードの(一般的な)スマートポインタを返す方式
これはshared_ptrなど安全とされているスマートポインタを返すためメモリ使用上は安全
しかしポインタ先がヒープへ戻されていないことしか保証がない
つまり(B)と同様にリンクリスト自体からの削除が起きている可能性がありそれを知る方法がない

(D) データを挿入して作られたノードを管理しているリンクリスト内部の何らかを返す方式
リスクの高い(B)や(C)と異なりこの方式は安全かつ整合性が維持される
もしノードがリンクリストから削除されていればそれに対して対応ができる
この返されたデータを用いて新たなデータをその位置に挿入する時に元ノードが削除されていた場合
(D)-1. 挿入はされず既に元ノードが削除されていると知らせる
(D)-2. 知らせずに削除された元ノードの次に有効なノードの位置に挿入する
などリンクリストの仕様や用意されたメソッドにより異なるようだ

以上まとめると現実的に安全に使える方式は(A)もしくは(D)となっている
例えばC++の標準リンクリストstd::listでもこの(D)方式を採用しており
insert()はリンクリスト上をその位置から順に辿っていくイテレータを返す
0593デフォルトの名無しさん垢版2021/11/29(月) 12:52:17.03ID:qK4xTYr2
>>585みたいなことできる連結リストって、
Rustでも作れると思うんですけど
Unsafe全振りにはなると思うけど
0595デフォルトの名無しさん垢版2021/11/29(月) 15:16:40.92ID:LzdsKRCS
> 2. リンクリスト + リンクリスト

それだとさあ
最初から主張してるO(1)ランダムアクセスできないけどいいのw
配列だからこそi番目が定数時間でa[i]でアクセスできるんでしょ
0596デフォルトの名無しさん垢版2021/11/29(月) 15:56:54.32ID:tPktcSTu
>>592
やはりポインタを直接返さないんだな
ポインタだけもらって保持していてもそのノードがリンクリスト上でアクティブかどうかすらわからないもんな
0597デフォルトの名無しさん垢版2021/11/29(月) 16:56:11.45ID:KFZ7/agt
C++ の std::list はポインタではなくイテレータで扱うけど、実質ポインタと同じだぞ。
Debug ビルドだと二重 erase は検出してくれるけど、Release ビルドだとセグフォで落ちる。
0598デフォルトの名無しさん垢版2021/11/29(月) 17:12:06.45ID:tPktcSTu
そもそも途中ノードのポインタを保持していても普通の使い方だとそこへ挿入することないよな
リンクリストの先頭挿入か最後挿入かあるいは何らかのデータ順になっていてその位置に挿入だよな
可能性があるのはエディターくらいだけどそれならばカレントポジションをエディター用リンクリストの中で保持した方が便利
0599デフォルトの名無しさん垢版2021/11/29(月) 17:31:01.57ID:uM27l7Qv
ポインタだらけのデータ構造ってそれをファイルに保存するとかネットで繋がった別のマシンに送るのって大変じゃない?
ポインタの代わりにインデックス使ってればそのままシリアライズできるけど
0600デフォルトの名無しさん垢版2021/11/29(月) 17:39:15.23ID:KFZ7/agt
というか std::list はメモリも速度もコスト高いし、普通は std::vector を使う。
途中への挿入・削除が頻繁に発生するようなら std::list の使用も検討するべき。

ノードが既に分かっているとして、当該ノードの保持する値へのアクセスが O(1) で
行えるのは当たり前の話で、これが出来ないコンテナって存在するのか?
リンクリストは(既に分かっている)ノードの削除、
(既に分かっているノードの前後への)挿入が O(1) で行えることに意味がある。
0601ハノン ◆QZaw55cn4c 垢版2021/11/29(月) 19:03:52.90ID:NTguHH8l
>>585
C でも rust でもいいから動くソースを出してもらえませんか?ここ、確かプログラム板でしょ?
0602デフォルトの名無しさん垢版2021/11/29(月) 19:45:36.73ID:27e/xIh/
>>599
多くのケースではシリアライザ手書きしないから気にならないのでは
例えばrustならserdeがLinkedList対応してるからVecと同じ手軽さでシリアライズ・デシリアライズできると思われる
0607デフォルトの名無しさん垢版2021/11/29(月) 21:27:48.38ID:4MgUQE5v
>>606
それ怪しいな
LinkedList型はser/de定義されていて先頭保持してるところから順にたどって全体を巡るとして
途中ノードのポインタを渡されてもまずそのノードだけ対象になるのかそれとも次をたどるのか曖昧
もし同じように順にたどるとしてもLinkedListの一部分が出来上がりそれに意味があるのか疑問
0608デフォルトの名無しさん垢版2021/11/29(月) 21:32:39.40ID:2AI6LBe9
そりゃsafety売りにしてる言語が実はunsafeばっかとか言えませんよね。普通の感覚ならね。
0609デフォルトの名無しさん垢版2021/11/29(月) 22:50:59.13ID:27e/xIh/
>>607
CursorではなくてLinkedListのシリアライズに対応してるから必ずリストの先頭からのシリアライズ

>>608
なぜ?
safeを売りにするという言葉をどのように解釈しているの?
0610デフォルトの名無しさん垢版2021/11/29(月) 22:59:12.77ID:qFPvT22S
あわしろ氏はC++の危険性を見過ごせないと言ってた。
ダングリングポインタは諸悪の根源と言える。
0612デフォルトの名無しさん垢版2021/11/30(火) 00:58:11.71ID:oK3YB4Sq
>>595
ll2にllの検索条件に合うノードのポインタを順に入れて言った場合、
llのノードが順序がバラバラで入っていることになり、
ll2を先頭から順にシーケンシャルアクセスすると
llはランダムアクセスされることになる。
なお、ランダムアクセスとはシーケンシャルアクセス以外のアクセスを全て指す
言葉。
0614デフォルトの名無しさん垢版2021/11/30(火) 02:01:49.64ID:Y6JwF3m3
>>612
> ll2にllの検索条件に合うノードのポインタを順に入れて言った場合

なぜポインタを辿って遅くて不便なリンクリストを使うの?
順に入れるならベクタを使えば速くてメモリも食わないのに
0615デフォルトの名無しさん垢版2021/11/30(火) 02:45:59.65ID:oK3YB4Sq
>>614
そこをベクタにしてしまうと、せっかくのリンクリストの特性であるところの
O(1)性が完全な意味では維持できなくなるからだよ。
0616デフォルトの名無しさん垢版2021/11/30(火) 03:29:37.11ID:oK3YB4Sq
リンクリストは、損して得取れの考え方だからね。
配列は、ちょっとしたことで使うには良いが、
一見得してるようだが、複雑なことをやる場合には損することが多い。
0617デフォルトの名無しさん垢版2021/11/30(火) 03:32:42.38ID:Y6JwF3m3
>>615
リンクリストはランダムアクセスO(n)で遅いから特殊な用途でしか使われていない
ほとんどのケースではランダムアクセスO(1)のベクタが使われている
シーケンシャルアクセスだけならどちらも同じだけどポインタをたどるリンクリストは遅くてメモリも余分に使って結果不利
0619デフォルトの名無しさん垢版2021/11/30(火) 03:56:01.94ID:oK3YB4Sq
今後、秀才か天才しか書込み禁止。
そうでないと、まともな議論にならない。
IQ130以上限定。
0623デフォルトの名無しさん垢版2021/11/30(火) 12:21:03.90ID:M/ykbWDe
>>622
細かくは読んで無いけど
限定がなければ当然同じ計算オーダーの構造は作れるはず
いずれもリソースを限定しなければチューリング完全な言語であるわけだから

あとは限定次第
特定のコンテナを使う場合とか安全性とか
各言語での流儀とか
0625デフォルトの名無しさん垢版2021/11/30(火) 17:35:34.91ID:BH845EGe
>>623
>限定がなければ当然同じ計算オーダーの構造は作れるはず
>いずれもリソースを限定しなければチューリング完全な言語であるわけだから
確かに同じ計算オーダーの構造は作れるが、制限を回避するためにかなり遅くなる。

例として、参照もポインタも無いBASIC言語で、配列だけを使ってポインタを
模倣することも可能ではあり、実際にポインタと同じような計算オーダーを
持つものをそれでも実現可能ではあるが、「速度係数」が大きくなる。

Rustの場合、safeモードでは、1つのリンクリストに対して、読み書きが出来る
参照を複数同時にはマシン語レベルの生アドレスとしては持つことが出来ない。
その制約を回避するため、別の配列をわざわざよういして、アドレスの代わりに
配列の添え字番号を持つ整数型を参照型の代替として用いるやり方が、
提示されていた。
0626デフォルトの名無しさん垢版2021/11/30(火) 18:12:13.96ID:Y6JwF3m3
>>625
Rustでも生ポインタを使えば制約は一切ない
ソースコード>>542

さらにリンクリストで生ポインタを返すのは危険なので一般的にもっと安全な形が取られている
リンクリスト分類まとめ>>592
0628デフォルトの名無しさん垢版2021/11/30(火) 18:15:08.99ID:rIKeeiBO
safe Rustが要求するレベルの安全性(特に共有参照が存在する間はそれを変更できない)を実現するには、
C言語だろうとC++だろうと排他機構が必要になって、実行時コストを払わずに行うことは不可能
0629デフォルトの名無しさん垢版2021/11/30(火) 18:16:39.59ID:BH845EGe
>>628
C++は、プログラマが自分の頭で考えて、安全性を確保する思想だから、
あなたの言ってるコストは元々必要ないという思想。
0631デフォルトの名無しさん垢版2021/11/30(火) 18:26:13.61ID:BH845EGe
>>629
[補足]
なお、マルチスレッドにおける、排他制御はCやC++では必ず必要。
それはプログラマが頭で考えても省略できない。

なお、シングルスレッドにおける Rustの借用規則のような仕組みを
に「排他制御」という言葉は通常は使わない。
0633デフォルトの名無しさん垢版2021/11/30(火) 18:35:01.07ID:rIKeeiBO
イテレータをポインタだと思ってやっぱ複雑なC++じゃなくてC言語で話そうとか言っちゃう人が自分の頭で考えて安全性確保できる秀才ってマジですか
0634デフォルトの名無しさん垢版2021/11/30(火) 18:39:16.69ID:TJjyIr2u
Rustで書かれたFirefoxはC++で書かれたChromeより三倍以上の安全性を持つ。
0635デフォルトの名無しさん垢版2021/11/30(火) 18:41:46.86ID:BH845EGe
>>633
なぜC++で説明しないのかといえば、std::listは、std::vectorなどの
他のコンテナと同じ使い勝手にするために、リンクトリスト本来の
アルゴリズムとは異なって実装されてしまっている可能性があるから。
0636デフォルトの名無しさん垢版2021/11/30(火) 18:42:00.53ID:Y6JwF3m3
>>631
シングルスレッド内のマルチタスク(いわゆるグリーンスレッド)でも競合は起きます

例えばポインタを得た後にファイルや通信の読み書きを行えばシングルスレッド内の別タスクに切り替わります
その別タスクが人間UIから指示でリンクリストの一部削除も起き得ます
元のタスクに切り替わった時に保持してるポインタの先は既に削除されて存在しないかもしれません

したがってシングルスレッドでも競合対策は必要です
0638デフォルトの名無しさん垢版2021/11/30(火) 18:44:23.35ID:BH845EGe
>>636
でもそのことを通常、「排他機構」とは言わないハズ。
独自定義の言葉は混乱するので使うべきでない。
0639デフォルトの名無しさん垢版2021/11/30(火) 18:46:28.71ID:TJjyIr2u
>>637
クレジットカードやパスワードが既に。
0641デフォルトの名無しさん垢版2021/11/30(火) 18:56:55.23ID:TJjyIr2u
シグナルハンドラの中と競合が起きないようにするのは、排他と呼んでますよ。
0642デフォルトの名無しさん垢版2021/11/30(火) 19:00:10.44ID:BH845EGe
>>640
言葉は知らない。

ただし、MicrosoftのWinFormsやMFC、Win32だと、メッセージキューを
上手く使うことができていて、1つのメッセージ(イベント)を処理中は、他のメッセージを
受け付けないようにする仕組みになっているので、自分のアプリのイベントハンドラに
二重に入ってくることがない。だから、あなたの言っているような状況は絶対に起きないように
なっているため、心配要らないし、それを一般プログラマがコードで避けることも
通常は必要ない。

JSだとメッセージキューを上手く操れないためにイベントが二重に入ってくる
ことを一般プログラマが手作業で避ける必要がある場合が出てくるが。
0643デフォルトの名無しさん垢版2021/11/30(火) 19:01:35.67ID:BH845EGe
>>641
JSは、二重にイベントが呼び出されることがあるから必要になるだけ。
マイクロソフトのMFCやWinFormsではそもそも起きない。
0644デフォルトの名無しさん垢版2021/11/30(火) 19:04:13.70ID:BH845EGe
>>643
[補足]
正しくは「JS」ではなくて、ブラウザ上でJSで使ったイベント処理の話。
onclick="func()" みたいに書くやり方のこと。
イベントキューは有ることはあるが、一般プログラマが細かく制御できない。
Win32やMFCでは細かく制御できる。
0645デフォルトの名無しさん垢版2021/11/30(火) 19:08:01.74ID:Y6JwF3m3
>>642
Microsoftは全く使うことがないので知らないのですがそんなダメ仕様なの?
さすがに通信I/O待ちになったら別タスクに切り替わると思いますよ
少なくとも他のまともなシステムならば別タスクへと切り替わります
ずっと通信I/Oを待ち続けるのは明らかに時間の無駄ですから
0647デフォルトの名無しさん垢版2021/11/30(火) 19:46:30.08ID:WEl8d1PC
>>645
「タスク」って言うのが、他のアプリのプロセスやスレッドに切り替わるというの
なら、その通りだが、自分のアプリのイベント中に、自分のアプリの別にイベントが
発生するのはプログラムが複雑になるので、MicrosoftのGUIではわざと避けられて
いる。でも、そのおかげでGUIプログラムが簡単に書けるようになっている。
0648デフォルトの名無しさん垢版2021/11/30(火) 19:48:30.63ID:Y6JwF3m3
>>647
そんな効率の悪いお子様向けメニューがあるのですね
あなたはそんな効率悪いダメ環境でしかプログラミングしたことないのですか?
0649デフォルトの名無しさん垢版2021/11/30(火) 19:56:09.78ID:WEl8d1PC
>>648
ドローツールで、メニューからファイル保存ハンドラを起動して、
ファイル保存処理中に、マウスをクリックして、マウスイベントを起動して、
データを変更する必要は無いよね。
だから、マイクロソフトのMFCやWinFormsでは、最初から、メニューハンドラを
実行中は、マウスイベントが起動しないように設計されている。
同様に、あらゆるイベントは、必ず1つずつ順番に実行される設計になっている。
0650デフォルトの名無しさん垢版2021/11/30(火) 19:59:43.64ID:Y6JwF3m3
>>649
それだとウェブブラウザすら実装できませんね
そういうお子様向けメニューがあると勉強になりました
ありがとう
0651デフォルトの名無しさん垢版2021/11/30(火) 20:11:18.02ID:s7fhQ2Tk
>>643
二重にイベントが呼び出されるとはどういう現象を指しているのでしょうか
またJSはシングルスレッドなのでデータ競合は発生しないと思うのですが

そもそもなぜ突然JSの話が出てきたのですか
シグナルハンドラとイベントハンドラを混同していませんか
0652デフォルトの名無しさん垢版2021/11/30(火) 20:16:25.11ID:WEl8d1PC
>>651
JSは、ファイルI/Oを非同期でやりたがる人が居て、例えば、
Unixの write() は、書き終わるまでその場で停止して、書き終わってから
次の行から実行が再開される。
ところが、JSの場合は、書いている間に、イベントキューの読み取りに戻って
別のイベントが起動される可能性が生まれる。
だから、メニューからファイル保存を選んで、write() 文に相当する関数を
呼び出すと、まだ保存が終了して無いのに、別のメニューをもう一回起動
できるようなアホな状況が生まれる可能性が出てくる。
0653デフォルトの名無しさん垢版2021/11/30(火) 20:20:26.40ID:Y6JwF3m3
>>652
それはJS限定の場合ではなく
まともなシングルスレッド並列プログラミングならどれも同じで他へ切り替わります
通信I/Oで止まってしまい他へ切り替わらない方がおかしい
0656デフォルトの名無しさん垢版2021/11/30(火) 20:32:20.30ID:s7fhQ2Tk
>>652
そりゃノンブロッキングなAPIを使ったらそうなるでしょ
処理が先に進んで困るならブロッキングなAPIを使うかawaitなりすれば良いのでは
なにを問題に感じているのかがわかりません
0659デフォルトの名無しさん垢版2021/11/30(火) 20:46:39.91ID:s7fhQ2Tk
>>658
グリーンスレッドの話にMFCやWinFormsの描画スレッドの話を持ち出すのはなんの反論にもなってないと思うのですが...

そもそも >>628 のいう排他は rust の aliasing xor mutability の意味での排他なので論点がすれてます
0660デフォルトの名無しさん垢版2021/11/30(火) 20:52:01.15ID:Y6JwF3m3
>>657
通信やI/O待ちしたままシングルスレッド内で他へ切り替わらないと主張しているのですからウェブブラウザを実装するのは無理でしょ
JavaScriptを含むまともなシステムのように通信やI/O待ちの時はシングルスレッド内の他のタスクへ切り替わるのが普通であってそれだと実装できます
0661デフォルトの名無しさん垢版2021/11/30(火) 20:53:04.96ID:WEl8d1PC
あんたたち、まず、世界標準であるところの、マイクロソフトのGUIプログラミング
の構造を理解しなくては。基本は、MFCとWinForms。
0662デフォルトの名無しさん垢版2021/11/30(火) 20:54:17.71ID:WEl8d1PC
>>660
あなたは、ゲームで、それぞれのキャラクターが同時に動いて見えるのは、
非同期に動いていると思ってる人?
0663デフォルトの名無しさん垢版2021/11/30(火) 21:02:11.91ID:Y6JwF3m3
>>661
マイクロソフトには興味ないのでどうでもいいです
シングルスレッドである限りは通信やI/O待ちで他へ切り替わらずに全体が止まってしまってはどうしようもありません
通信やI/O待ちになるところで他のタスクへ切り替わるのが普通のシステムです
0664デフォルトの名無しさん垢版2021/11/30(火) 21:07:36.86ID:WEl8d1PC
>>663
伝統的な理解では、その場合の、タスクというのは、JSのasyncのタスクの事
ではなくて、別のアプリの「プロセス」のことである事は分かってる?
JSのような意味でのタスクだと切り替えた瞬間にアプリがおかしくなってしまう。
だから、あなた自身が分かっているような「排他処理」が必要だと考えに至る。
ところが、MSが採用している標準的なGUIシステムでは、最初からそうならない
ようになっているから、その心配が無い。
0665デフォルトの名無しさん垢版2021/11/30(火) 21:22:23.73ID:Y6JwF3m3
>>664
いいえ
ここでタスクと呼んでいるのはそのJSだけでなくRustでも同じで
シングルOSスレッドの中でも複数が動くタスクのことであって
別名グリーンスレッドと呼ばれる並行プログラミングでの単位のことです

シングルスレッド内のタスクの中でI/Oや通信待ちとなる時は他のタスクへスケジューラーが切り替えます
別タスクへ切り替えないとI/Oや通信待ちのままプログラムが動かなくなるからです
0666デフォルトの名無しさん垢版2021/11/30(火) 21:31:24.72ID:WEl8d1PC
>>665
その仕組みはどれくらい採用されているの。
世界標準は、マイクロソフトの MFCとWinFormsなんだが、それはそんな
仕組みは採用して無いぞ。
0667デフォルトの名無しさん垢版2021/11/30(火) 21:37:25.41ID:Y6JwF3m3
>>666
マイクロソフトには興味がないので知りませんが並行プログラミングの常識ですよ
少なくともウェブブラウザで動くJavaScriptは通信I/O待ちで止まったままにはなりませんね
その間も例えば人間が操作すると反応するように他のタスクが並行して動いています
0668デフォルトの名無しさん垢版2021/11/30(火) 21:50:24.93ID:cmlIqpOQ
>>667
JavaScriptはスクリプト言語だし、ブラウザのセキュリティー的にもあえてそう設計されているから、
C++やRustのようなコンパイル言語とは比較出来ないのでは?
0669デフォルトの名無しさん垢版2021/11/30(火) 21:58:56.83ID:Y6JwF3m3
>>668
Rustでも普通にasync-stdやtokioを用いてシングルスレッドでマルチタスクの普通のプログラムを組むと全く同じですよ
もちろん通信やI/O待ちになると別のタスクへ切り替わります
0670デフォルトの名無しさん垢版2021/11/30(火) 22:24:13.84ID:cmlIqpOQ
>>669
結局の所、Rustって基本は非同期で、プログラマが await-std や tokio を使って
明示的に非同期プログラミングするってことですよね。
それだったら C++ や Windows の WinForms/WPF アプリでも非同期プログラミングのフレームワークを使えば同じ事。

あなたのこれまでの投稿内容を見て、JavaScript では全てが勝手に非同期で動くと私は受け取りました。
0671デフォルトの名無しさん垢版2021/11/30(火) 22:47:13.22ID:Y6JwF3m3
>>670
つまりWindowsのシングルスレッドのプログラミングでも通信I/O待ちになると他のタスクへ切り替わるわけですね

そうすると元々の話
シングルスレッド内でもマルチタスクならば競合を避けるために何らかの排他的な制御が必要、と合意できますよね
そしてその排他的な制御が無ければ他のタスクにより書き換えや削除も起き得るということがわかっていただけましたでしょうか?
リンクリストか否かに関わらず全てのデータ構造で。
0672デフォルトの名無しさん垢版2021/11/30(火) 22:53:37.50ID:WEl8d1PC
>>671
>つまりWindowsのシングルスレッドのプログラミングでも通信I/O待ちになると他のタスクへ切り替わるわけですね
Win32の場合、ファイルI/Oは、通常は同期式だが、特殊な場合には非同期に
することも出来ることは出来る。
しかし、その場合、プログラミングが難しくなるので上級者向きで、
初心者はやるべきではない。
その場合、もちろん、何らかのフラグで危険な状態になるのを防ぐ必要がある。
0673デフォルトの名無しさん垢版2021/11/30(火) 23:04:55.17ID:Y6JwF3m3
>>672
このスレで初心者用のお子様向けメニューの話をしても仕方ないでしょ
現在プログラミング界ではasync/awaitが普通となっている現状で非同期プログラミングは当たり前のことなので
プログラムが難しくなるから同期だけ使う、というケースだけを前提に考えては駄目ですよ
0674デフォルトの名無しさん垢版2021/11/30(火) 23:11:44.10ID:WEl8d1PC
>>673
>現在プログラミング界ではasync/awaitが普通となっている現状で非同期プログラミングは当たり前のことなので
JS業界では耳にするが、C++業界では耳にしないな。
0675デフォルトの名無しさん垢版2021/11/30(火) 23:18:26.84ID:WEl8d1PC
「C++では安全なプログラムが難しい」
と思ってる人も、「非同期I/Oを使わなければ成らない」と思い込んでる人が
多いのかもね。
実際は、非同期I/Oは高度なので避けることが賢明と考えられている。
同期I/Oでもほとんどの場合は十分に機能を果たし、十分に高速なプログラムになる。
イバラの道を避けることで安全なプログラムが簡単に書けるようになる。
0676デフォルトの名無しさん垢版2021/11/30(火) 23:30:35.59ID:Y6JwF3m3
>>674
async/awaitはJavaScriptだけだと思い込んでるの??
PythonからC#まで幅広くサポートされている
もちろんRustもね

>>675
非同期が難しいって、初心者なのにこのスレにいるの?
あとawaitは同期するので初心者でも使うよ
0677デフォルトの名無しさん垢版2021/11/30(火) 23:38:36.37ID:WEl8d1PC
>>676
JSがある程度以上高度なプログラミングができないのは、非同期を使おうと
する人が多いからも有るかも。しかも、それを推奨したりする人が多くて。
簡単な方法で十分なのに、敢えてロジックがこんがらがる方法を使う必要は無い。

昔から言われていることとして、初心者ほど、マルチスレッドや、高度な
メッセージ通信、Mutexやセマフォなどの同期処理に興味を持ちやすい、
ということがある。

そして、上級者ほど、ほとんどの目的ではそれらを使わなくても
十分に良いプログラミングできることを知っている。

初心者ほど独特の複雑な記法を好み、一行で何もかも書こうとし、
関数に分けずにラムダ式で書こうとする。

上級者ほど、単純で平易な書き方をしようとし、複雑な記法や難しい
仕組みは避ける。
0678デフォルトの名無しさん垢版2021/11/30(火) 23:51:36.86ID:Y6JwF3m3
>>677
あなたが全く理解できていないから
このスレに無関係なJavaScriptをデタラメに叩いている
メジャーな言語の多くでasync/awaitや類するものが導入されている
時代遅れのC++ですらC++20で半分だけ導入するらしいぜ
0679デフォルトの名無しさん垢版2021/11/30(火) 23:58:50.35ID:8WvE/rry
数学100点マンの人が
同期プログラミングしか出来ない初心者だと判明したことが大きいな
0680デフォルトの名無しさん垢版2021/12/01(水) 00:01:00.14ID:0/nHr1m/
>>678
全く理解出来て無いわけではなくて、Promise や then() や await も
使ったことは有ることはあって、色々テストしてみたが、理解が難しい部分が
残るなとは思った。
で、俺は馬鹿だと思うかも知れないが、これでも数学100点連続マンだったからね。
少なくともそれ位は数学が出来たのに、Promiseが易しい概念だとは思わない。
e.responseWith()や、e.waitUntil()も未だにちゃんと理解出来てる自信が無い。
async関数をthenの中に入れているような場合も、ちゃんとは理解出来て無い。
0682ハノン ◆QZaw55cn4c 垢版2021/12/01(水) 00:01:56.93ID:VU8XmWVx
>>677
>上級者ほど、ほとんどの目的ではそれらを使わなくても
>十分に良いプログラミングできることを知っている。

金子氏も Windows を信用せず自前で並行処理を記述していたというし、しかし本当なのでしょうか?誰か解析してください…
0684デフォルトの名無しさん垢版2021/12/01(水) 00:37:59.70ID:hYYowF9a
>>680
Promise(言語によってはFuture)が難しいって数学も苦手なんだな
Promiseは単なる先物であって内部はpending/ok/error(言語によって名称など異なる)の状態を持つだけ
async関数はPromiseを返すだけだしawaitはpendingじゃなくなるのを待つだけ
thenの引数はokとなったら呼ばれるだけ
一方でresponseWithやwaitUntilは上述のような言語の基本構成ではなく
ブラウザのWeb APIに過ぎないからそこをまず区別できないと
0685デフォルトの名無しさん垢版2021/12/01(水) 01:04:02.61ID:0/nHr1m/
>>684
関数の最後に○○をreturnするとPromiseでラップされるとか、qiitaなどでは
見つけられたんだが、公式サイトで見つけられなかった。
それと実際色々実験して見ると、単にコールバック関数を登録していると
すれば予想される順序とは異なった順序でconsole.log()文が呼び出されて
いたりした。
その順序はとても独特だった。

また、Proimseを解説する記事において、Aを解決するBなどという言葉が
多用されていたが、その定義を見つけられなかった。
推定は出来るが。しかし、定義が無いと分かりにくい。
0686デフォルトの名無しさん垢版2021/12/01(水) 01:30:16.63ID:hYYowF9a
>>685
公式を見なさい
RustではPromiseはFuture traitでゼロコスト設計
https://doc.rust-lang.org/std/future/trait.Future.html
Futureはpoll()を持ち呼ばれると以下の2状態いずれかを返す
・Poll::Pending
・Poll::Ready(val) 【Rustではエラー状態はなくResult<正常値,エラー値>で返す】
https://doc.rust-lang.org/std/keyword.async.html
asyncはFutureを返す

JavaScriptがそんなに好きならこちら
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Promiseは以下の3状態を持つ
・pending
・fulfilled 【正常値が得られた時】
・rejected 【エラー値が得られた時】
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
asyncはPromiseを返す

このように概念は全く同じ
ただしJavaScriptはPromise作れば自動的にスケジューラーに登録されてタスク切り替え実行されるが
Rustはゼロコスト設計だからFuture作ったら自分で好みのスケジューラーに登録してタスク切り替え実行される
もし非同期プログラミングが不得意ならば数学も不得意だろう
0687デフォルトの名無しさん垢版2021/12/01(水) 01:33:52.46ID:0/nHr1m/
>>686
というか、Promiseは自分では使いたくないから興味が沸かないし、
実験する時間も取りたくないのに、サンプルなどでは大量に使われてる
場合が多いからもある。
意味が無いものには興味が沸かないというか。
0688デフォルトの名無しさん垢版2021/12/01(水) 01:36:10.77ID:0/nHr1m/
なお、俺が数学が不得意に分類されるなら、全人口の99.99%位は数学が
超不得意になるだろうな。
0690デフォルトの名無しさん垢版2021/12/01(水) 01:46:47.59ID:0/nHr1m/
Promise知らないことは単なる知識。
O(1)やリンクリストの話は、イマジネーションの世界だから生まれつきの
頭の良さの影響が大きい。
Promiseを知らないことを馬鹿にされても、俺の意見が間違っていることには成らない。
0691デフォルトの名無しさん垢版2021/12/01(水) 01:52:57.27ID:0/nHr1m/
明らかに間違ってるのに、俺を馬鹿にしてくるのは、この分野は、
博士課程などにも馬鹿が多いからかもな。
どうみても生まれつきの頭は大したことが無いのに、大学に残ってるような
人が多い分野。
それで馬鹿なのに勘違いして、明らかに間違ったことをいつまでも信じ続ける
人が居る。
さらに悪いのは間違ったことを流布してしまう。
0692デフォルトの名無しさん垢版2021/12/01(水) 01:53:04.71ID:oI4zTDt2
rustの非同期ランタイムは非標準ライブラリで提供されているからフリースタンディング環境でも使えるものがあったりするんだけど
c++ の future とかコルーチンってその辺どうなんですか?
0693デフォルトの名無しさん垢版2021/12/01(水) 02:18:40.66ID:nZUH6NM1
非同期と同期のどちらがよいかは場合によりけりでしょ。
複数のクライアントから同時接続されるサーバだとあるクライアントと通信している間に別のクライアントからの要求を処理しないと効率悪いだろうし。
ネットからファイルを一つダウンロードして解凍して中のファイルを読み込むだけのプログラムだったら前の処理が終わらないと何もできないから同期処理で十分。
0694デフォルトの名無しさん垢版2021/12/01(水) 02:25:30.27ID:SFGWVOvC
>>690
知るか知らないかではなく
理解できるか理解できないかの違い
もし非同期プログラミングが出来ないならば数学も弱いとわかる

>>693
後者の初心者向けプログラミングだけしか理解できずに終わるか
それとも前者の普通のプログラミングもできるようになるかの違い
0695デフォルトの名無しさん垢版2021/12/01(水) 02:58:41.60ID:0/nHr1m/
>>694
需要が無いのに知っていることを自慢するって、真空管技術を知っていて
偉いと思ってるのと同じようなことだと思うが。
0696デフォルトの名無しさん垢版2021/12/01(水) 03:01:24.50ID:0/nHr1m/
>>693
通信の場合、マルチスレッドプログラミングなら意味はあることもあるな。
しかし、単一スレッドで非同期にすることにどれだけ意味があることか。
0697デフォルトの名無しさん垢版2021/12/01(水) 03:15:28.24ID:SFGWVOvC
>>695
需要があるから使われているし
さらに利便性を高めるためにどの言語もasync/await導入したり導入検討している

>>696
例えば1000か所から通信でデータを取ってくる場合
(1)順番に同期的に一つずつ順に1000回処理するの?
(2)マルチスレッド1000個生成するの?
(3)普通はシングルスレッドかCPUスレッド数(2個とか4個とか8個とか)分までのマルチスレッドにてスレッド内マルチタスクをして実行します

このようにマルチスレッドでも各スレッド内では複数のタスクが非同期に多数動きます
0698デフォルトの名無しさん垢版2021/12/01(水) 03:22:45.28ID:0/nHr1m/
>>697
使用用途は、通信に限られるような気がするな。
余り一般化して欲しくない。
面倒だから。
それになんかわかりにくい。
0699デフォルトの名無しさん垢版2021/12/01(水) 03:42:46.81ID:SFGWVOvC
>>698
このネット時代では通信しないアプリの方が例外的な特殊な存在
そして通信だけでなくヒューマンインタフェースも非同期に発生
その『それになんかわかりにくい。』から数学が苦手だと予想します
0700デフォルトの名無しさん垢版2021/12/01(水) 04:21:18.83ID:nZUH6NM1
OpenGLやCUDAでもGPUに処理をお願いする関数を呼んだら計算が完了する前に戻る非同期処理は一般的に使われているよ。
0701デフォルトの名無しさん垢版2021/12/01(水) 07:22:02.74ID:2cqvkUoy
>>698
GUIなアプリは非同期プログラミングが避けられないと思うぞ
でないと、何か処理するごとにユーザーに待たせることになる
シングルスレッドでも工夫次第で待たせなくは出来るが、かえって実装が複雑になってしまう
0702デフォルトの名無しさん垢版2021/12/01(水) 08:05:39.60ID:SFGWVOvC
>>701
ブラウザ上で動いているJavaScriptはシングルスレッドですが
スレッド内で非同期に複数のタスクが動くのでGUIに対応出来ています
例えばマウスが動いたりクリックされたりするたびに次々と新たなスレッドが起動したら重すぎて困ります
プロセス起動よりは軽いとはいえスレッド起動はかなりのコストがかかります
だからマルチスレッドではなくシングルスレッドで動いています
このようにシングルスレッド内で並行プログラミングできるところが非同期プログラミングの良いところです
0703デフォルトの名無しさん垢版2021/12/01(水) 08:19:28.96ID:SFGWVOvC
これはサーバー側も同じです
今どきサーバーは数万のクライアント接続が同時に来ても捌けますが
これを数万のスレッド起動で実装したらリソースが足りず動きません
実際にサーバーが使用するスレッド数は最大でも使用CPUが同時実行できるスレッド数で8個とか16個などだけです
したがってそのスレッド各々が何千や何万のクライアントを相手に並行して非同期に処理しています
0704デフォルトの名無しさん垢版2021/12/01(水) 08:56:34.20ID:Zovg4aIt
Windowsアプリの件はわかる気がするわ。
Wixdowsアプリ(イベントドリブン)はイベントのキャッチはシングルスレッドでやっているのでイベントの実行から終了は全て同期処理。
ただし、イベントの実処理(中身)は非同期で実行する(しているケースが多い)からイベントの実処理が終わらずとも次のイベントが実行されているってことなんじゃない?
イベントドリブンの認識間違ってたらごめんね
0705デフォルトの名無しさん垢版2021/12/01(水) 10:40:28.38ID:oI4zTDt2
数学100点の人はgoやったら良いのでは
同期プログラムと同じ書き方で非同期になるよ
0706デフォルトの名無しさん垢版2021/12/01(水) 11:14:17.47ID:SFGWVOvC
>>705
同期プログラムと同じ書き方といっても局所的な表面上だけだからgoroutine間のやり取りや制御で理解できなくなると思われる
そして同期プログラムと同じ書き方という点ならばasync/awaitサポートする任意の言語でawaitを付ければ同期的にプログラミングできるわけだけどこれも彼には厳しいかも
0707デフォルトの名無しさん垢版2021/12/01(水) 18:57:51.36ID:no3HGX5y
posixシグナル完全対応。
0709デフォルトの名無しさん垢版2021/12/01(水) 21:05:34.73ID:oI4zTDt2
彼がしきりにアピールする東大の入試数学やセンター試験の出題範囲だとBASICがせいぜいだから
非同期やデータ構造に対する理解を求めるのが酷だったか
0713デフォルトの名無しさん垢版2021/12/02(木) 02:35:29.16ID:nb2+kp22
>>704
イベントではなく、シングルスレッドでメッセージキューに溜まったメッセージを
1つづつ取りだして処理するので、1つのメッセージ処理実行中、同時に別のメッ
セージ処理が実行されることはないので、排他処理が要らない。

ところが、メッセージ処理の中で受信待ちとか発生するコードだと、タイムアウト等で
抜けるまでメッセージ処理が終了しないので、ウィンドウ再描画などのメッセージも
処理されず、見かけ上GUIが固まったようになる。

だから、通信とかは、マルチスレッド化する必要がある。 C/C++はOSが走ってない
ワンチップマイコンのソフト開発にも使われるので、言語仕様にスレッドを持ち込む
必要はないと思う。
0714デフォルトの名無しさん垢版2021/12/02(木) 11:04:55.74ID:yooJVl//
関係ないけどautoが動的な型付けだと思ってたわ
auto = automaticだろ
名前負けしてんじゃねーよ
クソ言語か
0717デフォルトの名無しさん垢版2021/12/02(木) 13:37:53.33ID:1aORNnKD
>>716
合っとるよ
そのへんはC10K問題などで知見が広まりプロセスやスレッドを増やすのではダメだと結論出ている
それ以降はスレッドの中で非同期にどれだけ多数のタスクをこなすかが勝負となった
0718デフォルトの名無しさん垢版2021/12/02(木) 15:03:03.48ID:2R2gcOCs
Cのauto
C++のauto
本来の仕様は一緒のはずなのに使われ方が違ってて笑う
0722デフォルトの名無しさん垢版2021/12/02(木) 20:09:00.51ID:3TzX18xa
>>415-416 シークする必要どうのこうの
>>583 アクセス用にArrayListを使う例
この辺↑の話題のやつを実装してみた
Rc<RefCell>をまず共有しておいて、中身へのborrow()や
borrow_mut()は最小限の時間で行えば十分じゃないかな? ダメ?
実行時にうまく中身を借用できているかは使う人次第ってことになる

https://ideone.com/bd0cFx
・注意:双方向リストだけど循環参照は未解決のまま
・注意:要素への参照を使っての操作はリスト側には未反映
 (front, backを正しく再設定し直したりはしないということ)
 (両端の要素の外側に追加したときとかおかしくなるはず)
・手元の1.8.0で主に動作チェック
・基本的によく分かってないので妙な箇所があるはず
・イテレータを提供したかったがよく分からなかったので諦めた
・fmt::Debug for LinkedList<T>は本来はもっとスッキリ書けるはず
・push_prev(&self, h)などが何も返さないのは、selfを返すかhを返すか
 どっちを返すのが自然なのかという判断に迷って決め切れなかったため
0724デフォルトの名無しさん垢版2021/12/02(木) 21:38:58.00ID:7kQFmmWN
c10kはリソース問題だからブラウザサイドでも同じだよな
5chのページとか見ると多数の広告やら何やら大量にコネクション貼りに行くけど非同期で並行にシングルスレッドでも余裕で可能
これが同期プログラミングしかできない人が作ると数十のコネクションに数十のスレッドを無駄に使うか
もしくはシングルスレッドで1つずつ順に時間をかけるかのどちらかとなる
0726デフォルトの名無しさん垢版2021/12/02(木) 22:21:10.00ID:UYYLW8tE
コネクション多数確立するという意味では同じだがC10Kと比較するのはおおげさすぎる
今時のブラウザは非同期処理の塊だろうからもっと良い例あるのでは
0727デフォルトの名無しさん垢版2021/12/02(木) 22:30:51.78ID:E1OmpA3W
ブラウザではそもそもHTML5の登場までマルチスレッド自体使えなかったし
そんな中でもAjaxでイベントによる非同期処理は要求されたし

ブラウザjsに関して言えばマルチスレッドのオーバーヘッドに耐えられず必要に駆られてっていう理由ではなく
従来のイベント非同期をPromiseで簡便に書けて、async/awaitでもっと簡便に書けて喜ばれた、というのが正しい理由でしょうね
0728デフォルトの名無しさん垢版2021/12/02(木) 22:41:56.03ID:mlkfy4i9
>>724
それブラウザがマルチプロセス・マルチスレッドで仕事をこなしてるからGUIアプリとして使いものになるんだぞ

まさかJavaScriptだけで実現できてると思ってたのか?
0731デフォルトの名無しさん垢版2021/12/03(金) 00:22:36.68ID:aPplovFu
>>722
リスト構造ってほとんど使わんなぁ。 C++だとインスタンスの配列じゃなくて、
インスタンスへのポインタ配列を使えば、配列サイズの拡張に伴う領域確保とコピー
が行われるのは、配列要素であるポインタだけなので、要素数が増えようが、複雑な
オブジェクトだろうが、処理時間は最小限で済む。

リスト構造の欠点はソートに弱いこと。 オブジェクトインスタンスへのポインタ配列
ならソートの場合でも、ソート対象はポインタの並び替えだけで、ポインタが指す
オブジェクトのインスタンスには一切触らない(コピーや再配置は行わない)で済む。

「100日後に退職する47歳」に出てくる「クイックソートの計算量」なんて質問をする
面接官は、記憶力が全ての学力試験が産んだ馬鹿でしかない。 現実問題としては、
ソートする必要がある時はソートしなければならない。 聞くべきは『効率的にソート
するには、どんなデータ構造を採用すべきか』である。
0733デフォルトの名無しさん垢版2021/12/03(金) 00:38:41.22ID:aPplovFu
>>697
GUIスレッドの裏で動く、通信専用のワーカスレッドを1つ作成して、順番に1000個
のサーバヘアクセスに行くのが簡単かつ現実的じゃないかな。

むろんコア数を調べてワーカスレッド数の上限を可変にしてもいいが、アクセス先
リストの消し込みやエラー処理とか自動リトライとか面倒になるし、そこらを頑張っ
たところで、実際のところほとんどの場合は回線速度で頭打ちになる。

それと、たとえスレッドが1000個作れても、実際の環境では、経由するルータや
相手サーバ側の制限などで、同じIPアドレスから、同時に1000個の通信セッション
が張れないことの方が多い。
0734デフォルトの名無しさん垢版2021/12/03(金) 00:40:38.11ID:RidNMi7I
n番目の要素とm番目の要素を入れ替えるのに
配列だとポインタの読み込み2回、書き換え2回で済むのに対し
単方向リンクリストだと読み込みmax(n, m)+4回、書き換え4回必要になるからこれだけでかなりの差が生じる
0735デフォルトの名無しさん垢版2021/12/03(金) 00:44:57.19ID:aPplovFu
>>732
配列と違って、リスト構造を構成する各要素は、メモリ空間上に隣接して配置されて
いないのでqsort()ではソートできない。 あと、リスト内に循環参照がないとしても、
リストをバラす際にコストが掛かる。
0739デフォルトの名無しさん垢版2021/12/03(金) 05:25:43.24ID:nNIjH1TY
>>728
前者はその通り
後者は違ってJavaScriptだけでもGUIアプリは普通に作れる
例えばNode.jsでQtベースの物は軽くて便利
0740デフォルトの名無しさん垢版2021/12/03(金) 05:44:07.66ID:nNIjH1TY
>>733
> 通信専用のワーカスレッドを1つ作成して、
> 順番に1000個のサーバヘアクセスに行くのが簡単かつ現実的じゃないかな。

それは昔の同期プログラミングのマズいやり方でとてつもなく遅くなってしまう

> 経由するルータや相手サーバ側の制限などで、
> 同じIPアドレスから、同時に1000個の通信セッションが張れないことの方が多い。

経由する普通のルータにそんな制限はないです
1000ヶ所へ取りに行くという話だから相手サーバー側には各々1つのコネクションしか貼られないため
通信セッションが張れないということもありません

> そこらを頑張ったところで、実際のところほとんどの場合は回線速度で頭打ちになる。

たった1000個でそんなことは起きません
数KBの1000倍は数MBですから
0741デフォルトの名無しさん垢版2021/12/03(金) 08:06:35.94ID:aPplovFu
>>739
それって、Qtライブラリ(JavaScriptではなく、CやC++で書かれている)が、マルチ
スレッド機能を持ってるだけでは?
0742デフォルトの名無しさん垢版2021/12/03(金) 08:48:42.45ID:10RvFZJW
>>739
そりゃC++だから軽いわな
でもってシングルスレッドかマルチスレッドかの話には基本的に関係ないわな

JSのシングルスレット非同期モデルで対応できるのは
I/O待ち等でCPUがidleになる場合か
ホスト環境が提供する別のプロセスやスレッドに処理をオフローディングできる場合だけ

デスクトップアプリでそこそこ重いSQLiteへの読み書きなんかをJS実行スレッドでやれば非同期だろうがGUIに顕著な影響がでる
だからJS使ってても当然マルチスレッド化する
0743デフォルトの名無しさん垢版2021/12/03(金) 09:01:39.32ID:aPplovFu
>>740
> それは昔の同期プログラミングのマズいやり方でとてつもなく遅くなってしまう

実際、書いたことある? Webサイトの複数ページを移動しながらスクレイピング
して、ダウンロードファイルのURLを取得し、HTTPまたはHTTPSでファイルを順次
自動ダウンロードする自分専用ソフトを書いて使ってるけど、ダウンロード中に
GUIのプログレスバーや転送量/速度などの更新や、キャンセルボタン等の関係から、
GUIスレッドと通信スレッドに分けてるけど、速度はほぼ回線速度と相手サーバーの
応答に依存だよ。

> 経由する普通のルータにそんな制限はないです
> 1000ヶ所へ取りに行くという話だから相手サーバー側には各々1つのコネクション
> しか貼られないため通信セッションが張れないということもありません

確かに1000個のファイル取得先が別々なら、相手サーバーのコネクションは1つだけ
でセッション数も制限を受けないけど、2000を超えると安物や古いルーターだとNAT
テーブルの制限に引っ掛かる気がする。

> たった1000個でそんなことは起きません
> 数KBの1000倍は数MBですから

そんな制約あったっけ?

ちなみに自分が書いたアプリでダウンロードしているファイルは、小さいもので数百KB
大きいと+数MBくらいで、1000個(総容量約3.5〜3.7GB)ダウンロードすると2時間〜
3時間くらいかな。

回線はSoftbank Air(非5G)で、今の時間帯だとGoogleのSpeedtestで、ダウンロードが
20Mbpsくらい。
0744デフォルトの名無しさん垢版2021/12/03(金) 09:06:26.24ID:aPplovFu
ちなみに、HTTP/HTTPSで速度を上げるには、市販ダウンローダーが実装している、
分割パート毎にマルチセッションで同時ダウンロードして連結する方法もあるが、
ダウンロード先が同じサーバーで、アクセス遮断されないようにというのもあって
1セッションでのダウンロードにしてる。

本当はロボットであることを覚られないよう、ファイル単位のダウンロード完了後に
ランダムな秒数の待ち時間をいれるべきだろうが、今のところやってない。
0745デフォルトの名無しさん垢版2021/12/03(金) 14:35:28.91ID:fdWJSRDO
>>743
> 20Mbpsくらい。
ということは、毎秒2MBくらいのダウンロード能力があり、1分あたりでは120MB、1時間あたり7GBくらいはダウンロードできるということになる

> 1000個(総容量約3.5〜3.7GB)ダウンロードすると2時間〜
> 3時間くらいかな。
めちゃくちゃ遅くね?
0746デフォルトの名無しさん垢版2021/12/03(金) 14:55:37.25ID:9vhBCv/o
そもそもlibevとかlibeventとかはCで書かれたライブラリでC++用のリンクヘッダもあるけどNodeやRustの
専売特許じゃない、むしろ後発でC10k、promise、async/awaitだとかいってるアホは市んでほしい…
C/C++では現状コールバック関数でしかない。もちろんC++22とか出てきてないものは除く
0747デフォルトの名無しさん垢版2021/12/03(金) 15:13:11.54ID:RidNMi7I
非同期プログラミングの先達という意味ではそうだけど
callback hell をなんとかするために生まれてきた promise や async/await にはそれはそれで価値を認めるべき
0748デフォルトの名無しさん垢版2021/12/03(金) 15:17:25.21ID:aPplovFu
>>745
時間帯によって速度は変わる。 MicrosoftからWindows 10のISOファイルを1つ
(ほぼ容量同じ)をWebブラウザで落としても、30分強で終わるどころか、ほぼ同じ
くらい掛かる。
0749デフォルトの名無しさん垢版2021/12/03(金) 15:25:42.29ID:fdWJSRDO
>>748
いや、それってMSのサーバ能力で律速されてるってことでしょ

そもそも
>> 通信専用のワーカスレッドを1つ作成して、
>> 順番に1000個のサーバヘアクセスに行くのが簡単かつ現実的じゃないかな。
>
> それは昔の同期プログラミングのマズいやり方でとてつもなく遅くなってしまう

に対する反論を試みようとしてるんだから、相手側の能力で律速するのなら「じゃやっぱマズいやり方だよね」ってことになるだろ
0751デフォルトの名無しさん垢版2021/12/03(金) 15:52:47.63ID:9vhBCv/o
別にasyncはコールバック関数を何とかするために生まれた訳じゃない、勘違い甚だしいw

同期関数という普通の関数と、見た目上は同様に見えるように考えられただけで価値なんてほんの少ししかない。
むしろこのキーワードの導入によりコードの汚染が酷く、さらに言うならI/Oバウンドや*nix割り込みベースや
そしてCPUバウンドな非同期(≒スレッド)と統一的に扱えないために複雑なフレームワークを導入する羽目になる。

一般的には、I/Oバウンドなブロック単位のI/O読み書き待ちでコールバックされることだけを主眼に置いて設計されて
しまったがために多くの言語で採用されているが、スレッドや軽量ルーチェンとは互換性ない場合が多い。

ただ副次的にコールバック関数のネストが解決されているように見えるだけに過ぎない。
0752デフォルトの名無しさん垢版2021/12/03(金) 19:35:25.25ID:3ner7aMO
C10Kというけど、いま使ってるパソコンだってスレッドが数千あるのに、クライアントが1万程度でいまどき問題ある?
0753デフォルトの名無しさん垢版2021/12/03(金) 20:15:24.75ID:XIVj35HM
有線LAN なら、200Mbps ぐらい出る。
無線にすると、10〜20

無線スポットから離れると、1まで落ちる
0754デフォルトの名無しさん垢版2021/12/03(金) 20:20:25.08ID:XIVj35HM
Elixir では、10万のプロセスを起動できる

これは、OS のプロセス・スレッドじゃないから。
Erlang 内の小プロセスだから出来る
0755デフォルトの名無しさん垢版2021/12/03(金) 20:32:10.63ID:3ner7aMO
そんなに起動して何に使うの?
0757デフォルトの名無しさん垢版2021/12/03(金) 22:07:37.69ID:xM1Kf0e8
>>751
非同期プログラミングの話をしているだけなのにそんなasync/awaitに限定するのがおかしいのではないかね
さらにいえばasync/awaitの話とpromise/futureの話を同類に捉えているからちゃんと理解していないのでは?
非同期関数をなにか特殊なもののように捉えているのも怪しい

非同期ブログラミングとは同期ブロッキングI/Oによる非効率で無駄な方法を排除するプログラミングであって
昔も今も中心部分にselectやepoll等のシステムコールを核とするループすなわち高度化した時のスケジューラーで成り立っている
そして読み書き可能になったら読み書きをするという極めて自然なプログラミング
もちろんこのスケジューラー部分で割り込みやタイマー含めて共通管理できるため「相性が悪く複雑になる」というのも間違いだ

もちろん読み書き可能になったら教えて!と最初に登録するところから始まるわけだから
読み書き可能になったぜ!と教えてもらう部分がコールバックとなるのは当然の話
だからそれをまとめて包んだ非同期関数は当然コールバックとなりI/O待ちブロックされる同期関数より極めて効率が良い

promise/futureはこの部分のインターフェース部分だけを抽象化しただけに過ぎず
この中身は単なる状態管理だから具体的なI/Oやタイマー等と関係なく共通して使える点もプログラミングの利便性を向上させている
そしてこれ自体はコールバックを無くしているわけではなく例えばクロージャを渡すメソッドなどを用意することでコードの見た目を改善している
これで非同期関数のインタフェースとして(直接)コールバック系と(間接に行う)promise/future系((およびその両対応))に分かれた

以上ここまでの話は生のC言語でも普通にプログラミング可能な話である (メソッド呼び出しを除く)
もちろんスレッドなんか存在しない環境でもシングルスレッドにて並行に動作するの非同期プログラミング
当然ながらマルチスレッドでも同じように動作させられる
0758デフォルトの名無しさん垢版2021/12/03(金) 22:08:57.91ID:xM1Kf0e8
>>757の続き

一方でasync/awaitは全く別の話
これだけはプログラミング言語による支援がないと実現できない
そしてこの導入目的は同期プログラミングしか出来ない人たち向けも含めて楽に非同期プログラミングするためであり
asyncと宣言した関数などの中ではawaitを付ければ見かけ上は同期プログラミングと同じ記述ができる!という改革
これによりようやく真にコールバックが利用側からは消えたので「コールバックを無くすため」というのも間違ってはいない

ではasync/await導入で非同期関数側はどう変わったか?
実は全く変わっていない、が正解
そのままpromise/futureを返す非同期関数と全く同じそのままである
つまりasync/awaitは非同期関数を利用する側だけの話という点が重要

以上で>>751氏も非同期プログラミングを正しく理解できるであろうか?
0762デフォルトの名無しさん垢版2021/12/03(金) 23:40:57.15ID:C/q0fsga
Goスレでも同じC#おじさんがRust/Goを学びかけて暴れてたから同じやつ
「真にコールバックが利用側からは消えた」なんてコールバック関数が消えたことはない。お前はHello worldでも
書いて満足してろwawaitの話とpromiseを同列に語ってんのもお前、「インターフェース部分だけを抽象化」なんて
RustにもC++にも無いしC#おじさん臭さが露骨に出てる
0763デフォルトの名無しさん垢版2021/12/03(金) 23:59:21.97ID:zNp8n16A
>当然ながらマルチスレッドでも同じように動作させられる
そんなのはC#のような一部であり、多くのasyncを有する言語ではスレッド境界は越えられないのでそれぞれの
スレッドがイベントループとイベントキューを有する。これはAスレッドで起こったイベントはBスレッドには
伝わらず”同じように動作させられる”なんてことは無い、実行の順序制御も当然バラバラ
C++20でもコルーチェンたるco_return, co_await, co_yieldがあるのに、鬼の首を取ったようにRustなどの
触りだけ触れていて優位性を語ってるアホはまじ市んでほしい
0764デフォルトの名無しさん垢版2021/12/04(土) 01:46:20.63ID:aNU60Xul
最近は、一度もWindowsプログラミングしたこと無い人が増えてるからな。
Windowsは伝統的に非同期をほとんど使わないことを知らない人が多いらしい。
0766デフォルトの名無しさん垢版2021/12/04(土) 03:17:48.45ID:6dkLKknu
>>763
>>当然ながらマルチスレッドでも同じように動作させられる
>そんなのはC#のような一部であり、
>多くのasyncを有する言語ではスレッド境界は越えられない

え??
Rustでは当然出来ますけど

>スレッド境界は越えられないので
>それぞれのスレッドがイベントループとイベントキューを有する。

え??
Rustではスレッド境界を超えつつ、それぞれのスレッドがイベントループとイベントキューを有することも出来ますけど

>これはAスレッドで起こったイベントはBスレッドには伝わらず

そこだけは正しいですw
しかし暇になったスレッドがいわゆるワークスティーリングすなわち他スレッドからタスクを奪ってからイベント登録しますから、

>”同じように動作させられる”なんてことは無い

同じように別スレッドで動作を継続できます

>実行の順序制御も当然バラバラ

え??
非同期だからバラしたタスク間の実行順序は例えば通信相手次第で変わりますけど
それは単純なワンタスク同期なマルチスレッドの時も同じです
実行の順序制御が必要な部分のみ制御の意味での同期を行うのも同じです
例えば10個のタスクで並行して10ヵ所からデータを取得してその平均を出すならば平均を出す直前で10個全てのタスクの完了を待つだけです

非同期プログラミングしたことがない人は間違った思い込み妄想だらけで大変
0767デフォルトの名無しさん垢版2021/12/04(土) 03:24:28.87ID:54seiSNt
Rust使ったこと無いけど健全なマクロはいいなぁと思う。
0768デフォルトの名無しさん垢版2021/12/04(土) 03:28:16.65ID:aNU60Xul
今言われているasync, awaitの「非同期」ってちょっと違うけど、意味的には擬似スレッドみたいな感じだな。
I/O全般というより、XHRやfetchやsocketのように遅いネットワーク通信を複数同時に待つ時に使う
時に便利な気がする。
nativeのファイルI/Oの場合、処理が完了するまで待つ方が便利だし、余計なことを考えなくて済むので
バグが少なくできるから、伝統的に同期方式を使うことが基本。
0769デフォルトの名無しさん垢版2021/12/04(土) 03:36:51.75ID:aNU60Xul
print "hello\n";
と書いた場合に、print文は端末(terminal)などの別プロセスでの処理が
完了するまで待つことが多く、実行完了するには時間が掛かるが、
これを一々非同期にして、print 文が完了するまでに別の処理をする、
というようなことはすべきじゃない。
一番いいのは、print 文が完了するまではそこで待機して、ちゃんと
それが完了してから次の文を実行すること。
つまり、同期的処理。
0770デフォルトの名無しさん垢版2021/12/04(土) 03:52:52.03ID:6dkLKknu
>>769
え??
awaitはその待機という同期的処理をするためにあります
したがって非同期のprint関数を呼んでも問題は起きずにその書かれてる通りになります
0771デフォルトの名無しさん垢版2021/12/04(土) 04:12:46.09ID:aNU60Xul
>>770
でもそのコード部分では見て無い場所で、イベントループに戻ってしまって、
別のイベントハンドラが起動してしまう可能性が生まれ、
せっかく通常のシングルスレッドプログラミングでは起きない良い特徴が失われる。
そのため、シングルスレッドなのに排他処理が必要となってしまう。
排他処理は間違うととても危険であって、プログラミングのかなり上級者でも
気を使う必要がある。
0772デフォルトの名無しさん垢版2021/12/04(土) 04:28:23.02ID:6dkLKknu
見かけ上はどちらも関数処理完了まで待機する形で同じですが

「同期の関数を呼んだ場合」
  →関数から戻って来るまでそのスレッドはブロックされる

「非同期の関数を呼んでawaitする場合」
  →そのスレッドがブロックされることはなく他にタスクがあれば並行して実行される

>>771
いいえ
その場合はそのタイミングで並行して実行されたら困るタスクを持たなければいいだけです

○ その時は他に並行して実行されるタスクを持たない
○ 並行して実行されてもよいタスクだけを他に持つ
○ 並行して実行されるタスクの動作に制限がかかるようにロック等を持つ
✕ 並行して実行されたら困るタスクを対策なしに他に持つ

選択肢はたくさんあります
これがプログラミングです
0773デフォルトの名無しさん垢版2021/12/04(土) 04:34:52.83ID:aNU60Xul
>>772
Win32/MFC/WinForms/JavaのSwing/Android/ブラウザのJSで
プログラミングしたこと有る?
イベントループやイベントって自分で定義するものでは無いから
「タスクを持たないようにする」
っていうのは現実には不可能だぞ。
0774デフォルトの名無しさん垢版2021/12/04(土) 05:07:10.24ID:6dkLKknu
>>773
もちろんRustでも自分でスケジューラを自作することは滅多になく
selectやpollなど使用のイベントループを自分で書くことはありません
それからここでのイベントとは当然selectやpollなどのイベントですから具体的にはファイルディスクリプタの読み書きOK等がイベントとなります
もちろんこの処理はスケジューラが担当するので自分で書かなくてもいいです
しかし新たなタスクを起こすかどうかはスレッドの時と同様にプログラマーの自由であり必要なら明示的に行います

JavaScriptの場合もイベントループを管轄するスケジューラはブラウザでもNode.jsでもシステムとして持っているため関知しなくてもよいです
ただしJavaScriptでは非同期関数を呼ぶこと自体が自動的にここでいう新たなタスクを起こすことになります
あとは例えばブラウザ自体が暗黙的に動作しているタスクとしてみなすことも出来てそのタスクから新たなタスクを発火することもあります
リスナー登録するタイプの利用時もそのパターンです
0775デフォルトの名無しさん垢版2021/12/04(土) 05:13:43.45ID:aNU60Xul
>>774
MFC/WinForms/JavaのSwing/Androidなどでは、マウスイベントやキーボードイベント、
メニューイベントは基本的に常時イネーブル状態になったままにして使うので、await
してしまうと、それぞれのハンドラに普通に入ってしまう。
そうなるとロジックが破綻するので排他処理するか、awaitする直前に、
一々ハンドラを disable にして、awaitの次の行に来た時に enableにする
必要がある。そんなメンドクサイことすべきじゃ無いし、そもそもdisable
にするなら、非同期のメリットも無い。
そもそもGUIスレッドは、イベントハンドラの二重起動は禁止すべきとされている。
0776デフォルトの名無しさん垢版2021/12/04(土) 06:02:11.33ID:6dkLKknu
>>775
プログラミング分野は無数にある中で
なぜそんな特殊な環境だけを唐突に持ち出すのかも含めて分かりません
先ずは適用可能な分野から始めて経験と知識を積んで的確に判断できるようになってから結論づければよいかと
0777デフォルトの名無しさん垢版2021/12/04(土) 10:01:49.43ID:wGH9SwaY
数学の天才と言い切った手前、後に引けなくなってきたか
自分の触ったことのある範囲でいいから弁解しなくちゃ
もうリンクトリストなんてどうでもいい、無知の印象を払拭するのが第一
0778デフォルトの名無しさん垢版2021/12/04(土) 16:50:56.54ID:Peev2Fa+
天才と言いつつテスト100点としか言えてない時点で程度は知れて馬鹿にされてるんだから今更取り繕わなくて良いのに
0780デフォルトの名無しさん垢版2021/12/04(土) 16:55:24.53ID:d5QmhWSv
>>778
数学や物理のテストは、B4 の白紙一枚をわたされて、これに回答とか証明を書け、みたいな感じですが、そんなテストで一度でも 100 点をとれるのなら、それはそれですごいとは思いますよ
0781デフォルトの名無しさん垢版2021/12/04(土) 17:09:21.39ID:Peev2Fa+
>>780
引き合いに出してたのがセンター試験だったり東大入試だったりで大学入試の成績を誇るしかない人なんだなって思っていました
0784デフォルトの名無しさん垢版2021/12/04(土) 17:40:33.98ID:EblMEd3X
どっちも中途半端な知識しかないのに他人の指摘は聞かないから救いようがない

隔離スレ立てたやつグッジョブ!
0785デフォルトの名無しさん垢版2021/12/04(土) 18:40:15.11ID:4fIXFJG6
>>773
あわしろ氏が言ってたけど、Win32ではメッセージループを自分で作るらしいですよ。
まあ、配送はDispatchMessage()でやってもらうんですが。
0787デフォルトの名無しさん垢版2021/12/04(土) 18:49:24.09ID:d5QmhWSv
>>785
Java の awt では、どこにメッセージループが隠れているのか、あわしろ氏に訊いていただけませんか?
0788デフォルトの名無しさん垢版2021/12/04(土) 18:51:13.15ID:d5QmhWSv
>>786
私の時代には、そういうのは転部転科でもしようとしない限りわからなかったかと、今は変わったんですね…
0789デフォルトの名無しさん垢版2021/12/04(土) 18:51:48.09ID:4fIXFJG6
>>787
了解です。
来週、職場で会うと思うので、聞いておきます。
0791デフォルトの名無しさん垢版2021/12/04(土) 18:54:08.07ID:wGH9SwaY
センター試験や東大入試は数学の天才を黙らせようとした人らが基準を示すため言い出したのであって
当の数学の天才は一度も何の試験かにすら言及していない
高校の定期試験ということもあり得る
0793デフォルトの名無しさん垢版2021/12/04(土) 19:00:26.50ID:d5QmhWSv
>>791
私はしませんが、仮に「自分は数学の天才である」と名乗りたいときに、どういう風に自分の天才性を形容するべきか、はいい演習課題になりますね
あまりマニアックなことをいってもスルーされるだけですし
0794デフォルトの名無しさん垢版2021/12/04(土) 19:21:42.11ID:5XDM8baS
私は分かりやすく>>621
他には
東大後期模試300点
数学偏差値90
東大数学科卒
など

普通は
論文数/論文引用数/肩書き(教授など)/受賞歴/特許出願数
などが実績ですが
私はその辺の実績はありません
0796デフォルトの名無しさん垢版2021/12/04(土) 19:27:28.34ID:4fIXFJG6
アカデミー賞受賞最新作はどうでしょうか?
アカデミックな感じで。
0802デフォルトの名無しさん垢版2021/12/04(土) 22:16:07.33ID:4fIXFJG6
コンビニエンスストアの天才。
0803デフォルトの名無しさん垢版2021/12/04(土) 22:29:30.68ID:d5QmhWSv
>>800
鋭い視点ですね
オーダーの話と実時間の話をシレっと往ったり還ったりするところなんかは、私には変だと思いましたね、アルゴリズムの評価はオーダーで行うのが普通で他はほとんどみない…

>>799
× 円
○ 球
0804デフォルトの名無しさん垢版2021/12/04(土) 22:41:59.72ID:4fIXFJG6
天才の心は、自分が天才になった時、初めて理解できるのではないでしょうか。
0806デフォルトの名無しさん垢版2021/12/04(土) 23:41:44.19ID:4fIXFJG6
美少女の国に行きたいが、美少女じゃないので入れない。
0808デフォルトの名無しさん垢版2021/12/05(日) 10:27:47.16ID:thYcMvTR
数学100点が自慢の自称天才と
歴史的に有名な超天才を比べる変なスレ

板的にはチューリングが出てこないのは変
0809デフォルトの名無しさん垢版2021/12/05(日) 11:52:13.76ID:KOPBFOTo
チューリングの話題はLGBT板で。
0810デフォルトの名無しさん垢版2021/12/05(日) 12:45:24.80ID:KOPBFOTo
じゃあ、モンティホール問題に納得できない人は、手を上げて。
0812デフォルトの名無しさん垢版2021/12/05(日) 13:23:53.66ID:KOPBFOTo
良スレ。
アゲ。
0813デフォルトの名無しさん垢版2021/12/05(日) 15:04:30.36ID:RsIoD/ak
>>803
>オーダーの話と実時間の話をシレっと往ったり還ったりするところなんかは、私には変だと思いましたね、
>アルゴリズムの評価はオーダーで行うのが普通で他はほとんどみない…
書くのが長くなるからオーダーで書いているだけで、オーダーだけでは正しい特徴を捉えられない
場合がある。
例えば、同じオーダーでも乗算や条件分岐の両方が使われているアルゴリズムとマシン語の
1クロックの命令1個にコンパイルされるものでは全然違う。
また、N個のデータを持っているハッシュ構造は、1回の検索は、数学的に厳密にはO(N)
だが、実験的(実際的)にはO(1)のように振舞うと言われており、厳密に扱うには、
オーダーの記号だけでは表現しきれない。
もし、オーダーだけで評価すればいいのなら、チューリング完全なあらゆる言語は、
同じアルゴリズムを使うことは可能で、同じオーダーの時間で計算できてしまうから、
速度比較には役立たない。
0814デフォルトの名無しさん垢版2021/12/05(日) 15:19:38.16ID:HAXCanWR
>>813
>1回の検索は、数学的に厳密にはO(N)だが、実験的(実際的)にはO(1)のように振舞う
ハッシュテーブルの構築は O(N) ですが、既存のデータをハッシュで引く割合が多ければ多いほど O(1) に近くなるでしょう
ハッシュテーブルには衝突がつき物ですが、そういうところも厳密に評価するのは難しいかもしれませんね

ただし、

>同じオーダーでも乗算や条件分岐の両方が使われているアルゴリズムとマシン語の
>1クロックの命令1個にコンパイルされるものでは全然違う。

そのとおりですが、それは所詮 O(f) の f の係数が違うだけでしょう、というか、そういうものはケースバイケースで一般論には載せ難いかと
そもそもあなたは、Σクロック(命令種)、で近似的に評価しようとしてますが、その姿勢は評価しますが、CPU 内の RISC 変換と並列実行、投機実行等までは及んでおらず、ある意味これも粗粗の近似だと思います
CPU 種類やメモリ構成などによって大きく変わるのですから、オーダーでの評価にとどめておくのが妥当なのでは?

>もし、オーダーだけで評価すればいいのなら、チューリング完全なあらゆる言語は、
>同じアルゴリズムを使うことは可能で、同じオーダーの時間で計算できてしまうから、
>速度比較には役立たない。

そりゃそうです、言語間の速度比較にオーダーを使う方が間違っています
総じて評価センスの問題かと
0816デフォルトの名無しさん垢版2021/12/05(日) 16:04:00.19ID:L/b/spZ8
>>814
>>1回の検索は、数学的に厳密にはO(N)だが、実験的(実際的)にはO(1)のように振舞う
>ハッシュテーブルの構築は O(N) ですが、既存のデータをハッシュで引く割合が多ければ多いほど O(1) に近くなるでしょう

あなたは、>>813
「また、N個のデータを持っているハッシュ構造は、1回の検索は、数学的に厳密にはO(N)
 だが、実験的(実際的)にはO(1)のように振舞うと言われており、厳密に扱うには、
 オーダーの記号だけでは表現しきれない。」
と書いてあることの意味が全く分かって無い。

秀才以上で無いと発言禁止だ。
0817デフォルトの名無しさん垢版2021/12/05(日) 16:12:34.15ID:L/b/spZ8
>>816
ハッシュ構造は、「一回の検索」でも、数学的には、O(N)の時間が掛かる。
ハッシュ構造へのデータの書き込みとは全く関係無い。
検索自体が、数学的にはO(N)なのだ。
しかし、実際問題は、Nが常識の範囲内の大きさではO(1)のように振舞うことが
分かっているので、とても高速。

数学的には、O(f(N))とは、Nを無限に大きくしても、処理時間をf(N)で割るとある
上限値未満であるという意味。ハッシュテーブルの検索は、Nを無限に大きくすると、
定数的ではないので、O(1)ではない。

なお、g(N)=O(f(N))のように書いた時の意味で定義されているが、左辺は関数で、
右辺は集合のようなもので、両辺が等しいという意味ではない。なので、記法として
O(1)=O(N)であるが、O(N)=O(1)ではない。

不定積分の等号も集合論的な意味であって、等しいという意味ではないと聞いたことが
あると思うが、それと同じような定義。
0820デフォルトの名無しさん垢版2021/12/05(日) 16:50:30.44ID:HAXCanWR
>>817
>しかし、実際問題は、Nが常識の範囲内の大きさではO(1)のように振舞うことが分かっているので

それには理由があるのでしょう?その理由はなんですか?「振舞うことがわかっている」という観測事実のみが根拠とは到底考えられませんね
>>814 が間違っているのであれば、あなたの解釈はなんですか?

>数学的には、O(f(N))とは、Nを無限に大きくしても、処理時間をf(N)で割るとある
>上限値未満であるという意味。ハッシュテーブルの検索は、Nを無限に大きくすると、
>定数的ではないので、O(1)ではない。

そりゃ、衝突が頻繁に発生するようになると、それを連鎖法で処理するか、あるいはオープンハッシュ法&セカンドハッシュ関数で処理するか、
いずれにしても N がハッシュテーブルサイズに比して大きくなりすぎるとO(1)から程遠くなるでしょう
しかし、今はハッシュテーブルサイズが N に比してそんなに大きくないことが前提だと思っていましたが、そういうハッシュテーブルの重要な性質を無視して N→∞にいきなり振るとか、やはり実装経験が不足しているとしか考えられません

あなたには、オープンハッシュ法でも連鎖法でもいいから、一度実装してみることをお勧めします、そうすれば、そんな無茶な話をふったり出来ないはずです
0821デフォルトの名無しさん垢版2021/12/05(日) 16:51:42.71ID:HAXCanWR
>>820
×今はハッシュテーブルサイズが N に比してそんなに大きくないことが前提だ
○今は N がハッシュテーブルサイズに比してそんなに大きくないことが前提だ
0822デフォルトの名無しさん垢版2021/12/05(日) 18:19:46.95ID:KOPBFOTo
INTEL Core N4200。
0824デフォルトの名無しさん垢版2021/12/05(日) 19:16:59.90ID:3Mcy6QkY
>>820
あなたは馬鹿すぎて議論が成立しない。
勉強しろ、とも言えない。
なぜなら、勉強しても無駄だと思うから。
0825デフォルトの名無しさん垢版2021/12/05(日) 19:54:51.36ID:HAXCanWR
>>823
話が噛み合いませんね、やっぱり私が馬鹿だからなんでしょうかね…
でも、仮にも計算機科学方面から解析を行っていただくのでしたら、C でいいから例示してほしいですよね

>>824
生まれてきてすみません…
0826デフォルトの名無しさん垢版2021/12/05(日) 22:25:34.77ID:MGzOS3+Z
Ruby のハッシュでは、データ数と共に、バケット数を増やしていく。
バケット数は、2 の累乗の次に現れる素数。
2^n + a, 2 <= n <= 30

8 + 3 = 11
16 + 3 = 19
32 + 5 = 37
64 + 3 = 67
128 + 3 = 131
256 + 27 = 283
512 + 9 = 521

データ数が、バケット数の5倍を超えると、ハッシュが再構成される。
再構成時には、極端に遅くなる

11 * 5 = 55 だから、データ数が56 個になると、バケット数が19 になる。
19 * 5 = 95 だから、データ数が96 個になると、バケット数が37 になる

バケット数は、2 の累乗で大きくなっていくから、
大きいほど、線形(全)探索に比べて、ハッシュが有利

増え方が、N に比例しなくて、log N に比例するから

例えば、2^20 = 百万で、2^21 = 2百万では、
線形探索では毎回、百万回増えるけど、
ハッシュでは、1回だけ再構築して、その後は、21回で見つかる
0830デフォルトの名無しさん垢版2021/12/06(月) 00:01:51.71ID:3rXx+R7R
ベンチをもっと気楽に行うために単体テストフレームワークを使ってベンチ書いてる。
0831デフォルトの名無しさん垢版2021/12/06(月) 00:03:31.65ID:kjD6KzfX
>>829
O(N)の定義は、Nを無限に大きくしていった時に、処理時間を N で割った時に
ある固定された上限値の定数未満になる、という意味だぞ。
O(log N)のハッシュは有り得ない。
0832デフォルトの名無しさん垢版2021/12/06(月) 00:07:28.71ID:kjD6KzfX
なお、ハッシュ値の最大数を動的に増やしていくのならば、本来のハッシュ構造ではない。
本来のハッシュ構造は振り分けられる量は固定サイズ。
だから、ハッシュ値の計算も固定されたアルゴリズムで処理が固定された関数で
行う。
色々と勝手に定義を変えてはいかん。
言葉を勝手に再定義すれば議論になるわけ無い。
0833デフォルトの名無しさん垢版2021/12/06(月) 00:25:08.26ID:3rXx+R7R
(キリッ)が抜けてるのでは?
0835デフォルトの名無しさん垢版2021/12/06(月) 00:49:48.95ID:3rXx+R7R
良スレ。
アゲ。
0836826垢版2021/12/06(月) 01:37:20.07ID:siDRvkcR
>>826
修正

>増え方が、N に比例しなくて、log N に比例するから

>例えば、2^20 = 百万で、2^21 = 2百万では、
>線形探索では毎回、百万回増えるけど、
>ハッシュでは、1回だけ再構築して、その後は、21回で見つかる

これはデータベースで使う、2分探索の事だった。
ハッシュは、バケット数で割った余りで決まるから、O(1)だった
0837デフォルトの名無しさん垢版2021/12/06(月) 01:49:17.06ID:kjD6KzfX
>>836
ハッシュの表の様なものが固定サイズであるところの
素朴なハッシュの検索は、Nが大きい時には、O(N)。N が小さい時には、O(1)。

Nが大きくなるに従ってその表を時々大きくしていくようなものは、
考慮の対象にはしない。
0838デフォルトの名無しさん垢版2021/12/06(月) 01:53:00.58ID:kjD6KzfX
>>837
[補足]
以下、ハッシュの表の様なものが固定サイズであるところの素朴なハッシュの検索
についてだけを考える。
ハッシュの中に入っているデータの個数が N 個の時に、あるキーを持つ
データを1個だけ探すのに掛かる平均時間を g(N)とすると、数学的には
g(N)=O(N)。
しかし、この g(N) は、g(N) = a N + b と近似した場合の a の値が極端に小さい。
なので、N が小さい時には、O(1)であるかのように振舞う。
そういう意味だ。
これで理解できないなら、数学的想像力や理解力が足りてない。
0840デフォルトの名無しさん垢版2021/12/06(月) 02:22:55.84ID:XuzXkdX2
>>839
この数学100点マンはRustを叩いてる人で常に生ポインタ派のC/C++史上主義な人
ただしコードを出したことがないのでプログラミング能力がないと推定されている
さらにオーダーについても勝手な定義で無茶な主張を繰り返している
0842デフォルトの名無しさん垢版2021/12/06(月) 02:33:01.01ID:kjD6KzfX
>>840
お前もとことん馬鹿だな。
コード書いても抽象理解が出来ない人には、そのコードの本質は分からんし、
こんなところに書ききれるわけでも無いからかけないだけだ。
なお、抽象 = シンボライズ、シンボリック
という意味で、曖昧や玉虫色という意味では無いぞ。
本質的な部分を記号化、定理化、規則化、一般化して理解できるようにしたもの
を「抽象化」と言う。
0843デフォルトの名無しさん垢版2021/12/06(月) 03:29:12.50ID:rYDKtnCr
linkedlistの計算量を勘違いし
平衡二分木とハッシュセットを混同する
数学100点マンがいると聞いて
0844デフォルトの名無しさん垢版2021/12/06(月) 05:30:40.66ID:lQ57RfmU
>>842
>こんなところに書ききれるわけでも無いからかけないだけだ。
スレじゃなくて、IdeoneとかGihubのgistに書いてもらえれば大丈夫ですよ
0845デフォルトの名無しさん垢版2021/12/06(月) 05:43:24.70ID:4SyL85E7
>>838
>、g(N) = a N + b と近似した場合の a の値が極端に小さい。…@
なぜですか?
ハッシュテーブルの実装方法から論じてみください
もしかして、あなたは@を数学の公理、みたいに扱っているのですか?そんなことではコンピューターサイエンスは無意味だし面白くないでしょう?
でもC/C++ 至上主義者というのなら、私と気が合いますね
0846デフォルトの名無しさん垢版2021/12/06(月) 08:46:35.08ID:XZMNlO6i
>>775
MFC(Win32)に関しては、メッセージキューとイベントは別物だぞ。 イベントは、
イベント処理中でも降って来る。
0848デフォルトの名無しさん垢版2021/12/06(月) 11:16:09.54ID:O1qGwT+t
ベンチマークもなしに実時間の話をされてもなぁ
しかも具体的な実装上の問題点の指摘もなく他人のベンチマークは信用できないとか宣われてしまうとこちらとしては会話しても意味がない人なんだと判断せざるを得ないんですよね
0850デフォルトの名無しさん垢版2021/12/06(月) 11:57:28.95ID:q0VGOju1
>>849
[補足]
確率論で証明することが出来るが、とてもめんどくさいので割愛する。
失礼だが、質問者のレベルから推測すると、ちゃんと書いても理解できない。
0851デフォルトの名無しさん垢版2021/12/06(月) 12:01:12.30ID:EOOuRFRK
>>845じゃないけど
最悪値が重要な用途もある
また、確率はデータの分布が決まってはじめて決まるもの
分布次第ではあなたの想定通りにはならない
0853デフォルトの名無しさん垢版2021/12/06(月) 12:43:27.37ID:XuzXkdX2
>>842
ここはC++ vs Rustスレなのだからコードを出さなければ何も判定できない
机上の空論ばかり書き綴るよりも現実に使われるCPUと向き合わなければならない

例えばRustの標準ライブラリHashMapでも用いているSwiss Tables法ではハッシュ衝突時の別エントリ探索にSIMD命令を用いている
CPU命令4つで16エントリ同時に探索候補を判別していきメモリキャシュも活かすようこのためのメタデータを連続領域に配置している
0854デフォルトの名無しさん垢版2021/12/06(月) 13:08:20.11ID:PE/XVSQC
>>852
値がガウス分布に従うとかなんらかの仮定をおいていると思うのですがあなたの言うランダム性とはなんですか
あらゆる分布を想定しているのですか
0855デフォルトの名無しさん垢版2021/12/06(月) 13:21:52.08ID:iO91q1zt
>>831
> O(N)の定義は、Nを無限に大きくしていった時に、
コンピュータサイエンスでアルゴリズムの評価をするときは、Nを無限にするなんて考えません
ハッシュアルゴリズムはO(1)でFA
0856デフォルトの名無しさん垢版2021/12/06(月) 13:46:42.22ID:lQ57RfmU
>>848
ずっとそんな感じ
計算量ではちゃんとわからない、コストがかかって遅くなる、とか言いつつ、忙しいから実装はできない、お前は馬鹿だから理解できない、みたいなことを数ヶ月に渡って大量に書き込み続けてる
数学でいつも100点取るらしいし、さぞ偉いお方なんでしょうなあ…
0860デフォルトの名無しさん垢版2021/12/06(月) 21:08:31.14ID:4qQbBrsy
ハッシュが衝突しやすいコリジョンデータを使ったDDos攻撃が出来るのでは?
0861デフォルトの名無しさん垢版2021/12/07(火) 13:11:29.70ID:jcfwZSTS
>>854
最大M個の振り分け能力があるハッシュ構造にN個の(key, value)ペアを
書き込んでいる場合を考える。
ただし、Mは 定数とし、N が大きくなっても拡張していかないものとする。
このとき、一回の検索に掛かる平均時間をg(N,M)とすると、
ほぼ、
g(N,M)=b・(ceil(N/(2M))
ただし、
・b は、一回の文字列比較に掛かる時間。
・ceil(x)は、xを越えない最小整数。
と書ける。これは、ほぼ、
g(N,M)=b・((int)(N/(2M) + 1)
    =(int)(N/(2M))*b + b
と書ける。Nが大きい時には、
g(N,M)=a*N + b
a = b / (2M)
と書ける。
Mが大きい時、aは、小さいが0ではないので、処理時間は、O(1)ではなく、O(N)である。
0862デフォルトの名無しさん垢版2021/12/07(火) 13:27:33.41ID:pFZAiCY5
Wikipediaでも明記されている
・ハッシュテーブルの検索や追加はO(1)
・ハッシュテーブルの拡張もO(1)

> ハッシュテーブルはキーをもとに生成されたハッシュ値を添え字とした配列である。
> キーを要約する値であるハッシュ値を添え字として値を管理することで、検索や追加を要素数によらず定数時間O(1)で実現する。
>
> 利用率が一定を超えた場合に、より大きいサイズのハッシュテーブルを用意して格納し直す操作が必要となる。これをリハッシュ (rehash) と呼ぶ。
> この操作はすべての要素のハッシュ値を再計算して新たなハッシュテーブルに格納するためO(n)であるが、
> 配列のサイズを指数的に拡張する事で、動的配列の末尾追加操作と同様に償却解析によって計算量をO(1)とみなす事ができる。
0863デフォルトの名無しさん垢版2021/12/07(火) 14:35:15.82ID:iH9Jzajc
>>862
例えば、M=128で、128種類のハッシュ値に振り分けられるなっている
ハッシュ構造の場合、N=128万にすると、1つのハッシュ値に1万個の
(key, value)のペアが対応している。
そして、1個のkeyを検索する時、平均的には、1万個の半分の5000回
くらいkey値の比較を行うと一致するものが見つかる。
なのでこの場合、1個のkeyに対する検索時間は
5000*(keyの比較に要する時間)
となる。
Nを128億にすると、
5000万*(keyの比較に要する時間)
になる。
0864デフォルトの名無しさん垢版2021/12/07(火) 14:52:05.46ID:iH9Jzajc
>>863
誤:128種類のハッシュ値に振り分けられるなっている
正:128種類のハッシュ値に振り分けられるようになっている

誤:5000*(keyの比較に要する時間)
正:5000*(1回のkeyの比較に要する時間) // ()内は、keyが文字列の場合、1回の文字列比較に掛かる時間。

誤:5000万*(keyの比較に要する時間)
正:5000万*(1回のkeyの比較に要する時間) // ()内は、keyが文字列の場合、1回の文字列比較に掛かる時間。

>>862
> 利用率が一定を超えた場合に、より大きいサイズのハッシュテーブルを用意して格納し直す操作が必要となる。これをリハッシュ (rehash) と呼ぶ。
>>861 の4行目で、リハッシュは行わないと断った。
はっきり、Mを定数とすると書いている。
0865デフォルトの名無しさん垢版2021/12/07(火) 17:09:08.05ID:Io+x78vq
数学100点マンの机上の空論がさらに輪をかけてるな

>>864
> 最大M個の振り分け能力があるハッシュ構造にN個の(key, value)ペアを書き込んでいる場合を考える。
> M=128で、128種類のハッシュ値に振り分けられるようになっている
> Nを128億にすると、5000万*(keyの比較に要する時間)になる。

つまり128億個のデータを128個のハッシュ値パターンでハッシュテーブルに格納か
現実の世界ではなく一人だけの特殊な妄想世界で空論
0873デフォルトの名無しさん垢版2021/12/07(火) 19:22:19.85ID:hXWP+cLq
>>861
あなたの言うランダム性の定義を伺いたかったのですが
挿入されるkeyはどのような分布に従う仮定なのですか
0874デフォルトの名無しさん垢版2021/12/07(火) 19:28:32.42ID:XGUQnarH
確率論では衝突の発生確率が一様分布と仮定した場合、衝突回数はポアソン分布に従う
0876デフォルトの名無しさん垢版2021/12/07(火) 19:51:15.50ID:EZ68mIS/
>>873
衝突が起きるとしても、5chのIDが被る程度の稀な確率となる程度のランダム性を想定しています。
0878デフォルトの名無しさん垢版2021/12/07(火) 20:15:39.60ID:EZ68mIS/
>>877
データに合わせてハッシュアルゴリズムを変更する、アダプティブ・ハッシュ・テクノロジー™をご提案いたします。
0879デフォルトの名無しさん垢版2021/12/07(火) 20:16:48.35ID:EfSST75b
結局のところ衝突回数が算術平均に従う場合はO(n)であるが、この場合確率そのものが極めて小さく分布の期待値が小さいためO(1)に極めて近いとしか評価の仕様がない
0880デフォルトの名無しさん垢版2021/12/07(火) 20:23:38.39ID:EZ68mIS/
>>813は、言語のバイナリ生成能力を論じるときに計算オーダーは意味がないと言っているのでは?
その理由として、同一の計算オーダーを持つアルゴリズム、あるいは同一のアルゴリズムから、どちらが優れたバイナリを生成できるか論じているので、それはベンチでしか判明しない、と挙げていると思うのです。
0881デフォルトの名無しさん垢版2021/12/07(火) 20:33:30.11ID:U30hRDTM
特定のアルゴリズムを特定の計算オーダーで実装出来ない言語もあるので
全く意味がない事はない
0883デフォルトの名無しさん垢版2021/12/07(火) 21:53:06.58ID:WxNsBn2X
リンクリストの話は?リンクリスト、皆のアドバイスを受け入れて辞め、ハッシュテーブルに絞ることにしたんですか…
0884デフォルトの名無しさん垢版2021/12/07(火) 21:54:51.19ID:EZ68mIS/
リンクトリストね?
0886デフォルトの名無しさん垢版2021/12/07(火) 23:07:18.00ID:APR/hTgK
>>866
処理時間を g(N)とすると、worst case ではなく、平均が、g(N) = O(N)。
O(N)という記号を使わずに、詳細に書くと、
g(N) = a * N + b
だが、利用されるハッシュ値の振り分け数が M 個の場合、
a = b / M
程度となり、M = 1024 の場合、a は、0.001 * b 程度の小さな値になる。

横軸を N、縦軸を g(N) とするグラフを書くと、一次関数となり、y 切片が b、
傾きが 0.001 * b 程度となり、ほぼ水平であるが、僅かに右肩上がりとなる。
もしこれが完全に水平なら O(1)。
今回の場合、非常に水平に近いが確実に単調増加であるので、O(1)のように
見えるが本当は O(N)。
0889デフォルトの名無しさん垢版2021/12/07(火) 23:18:01.46ID:APR/hTgK
>>888
[補足]
「グラフが水平なら O(1)」とは書いたが、「O(1)ならグラフが水平」とは
書いてない。
つまり、グラフが水平である事はO(1)であることの十分条件であるが、
必要条件ではない。

「グラフが水平 ⇒ O(1)」とは述べているが、その逆の
「O(1) ⇒ グラフが水平」とは述べて無いことに注意。
0890デフォルトの名無しさん垢版2021/12/07(火) 23:59:06.43ID:q8J3SSC4
>>886
それがworst caseの話なんだってw
amortized average caseがO(1)とみなせる前提をガン無視して
「ほらO(n)だろ」とか言ってても誰も相手にしてくれない
0892デフォルトの名無しさん垢版2021/12/08(水) 00:20:29.77ID:ixfpknHK
>>891
なお、数学の秀才なら気付くと思うが、この平均の式は、本当は正しくない。
ただし、大体は合ってる。
0893デフォルトの名無しさん垢版2021/12/08(水) 00:22:38.55ID:ixfpknHK
>>892
[補足]
何が正しくないかというと、本当は、ある箇所を2 で割る必要があるから。
例えば次のように :
g(N) = b * (N/(2M) + 1)
しかし、これでも、まだ少し正しくない。
0895デフォルトの名無しさん垢版2021/12/08(水) 01:51:55.62ID:/oyDmL+H
数学100点君は数学用語の定義を誤解釈しまくって理解してしまっている感じ
説明の内容からしても多分中高生か啓蒙書を読みかじったおじさんなんだろ
0896デフォルトの名無しさん垢版2021/12/08(水) 03:16:15.50ID:ixfpknHK
なんでここは、数学が理解できない人ばっかりなんだ。
だから、プログラマが馬鹿にされる。
0897デフォルトの名無しさん垢版2021/12/08(水) 03:18:58.91ID:ixfpknHK
C++ vs Rust を語る前に、せめて、数学的に明らかに正しいことを理解できるから
でないとどうにもならん。
それ以前の問題。
0898デフォルトの名無しさん垢版2021/12/08(水) 03:20:41.94ID:ixfpknHK
それと、科学者にとって最も大事なことは、頭の良さでも知識でもなく、
正直さだ。
自説を主張するために正しい主張を否定してはいけない。
0899デフォルトの名無しさん垢版2021/12/08(水) 03:21:17.48ID:H0CVJE/p
「ランダムアクセス」って任意の要素にアクセスすることを指すんだけど、乱択的に与えられた要素にアクセスすることをそう呼ぶんだと思い込んでる奴が複数いてクソワロ
0900デフォルトの名無しさん垢版2021/12/08(水) 03:25:58.49ID:ixfpknHK
>>894
結果は一時式でも、それを求めるには確率論以前に、イマジネーションが必要。
どこかに書いてある知識の組み合わせでは導出できない。
確率論は、自分の想像力が重要に成るので、計算力だけでは無理な分野。
書いてある定理を組合すだけでも導けない。
数学は、基礎の部分はイマジネーションで作られているから、頭の良い
人以外には作れない。
いくら勉強しても無駄。
0901デフォルトの名無しさん垢版2021/12/08(水) 04:31:15.37ID:VGgp1CiZ
ハッシュに格納するまでの過程は確率論でも格納された後はただのリニア検索だけの話にすり替わってないか?
0902デフォルトの名無しさん垢版2021/12/08(水) 08:47:15.25ID:qP3Pvuq5
>>900
誰でも後から客観的に検証できる性質が数学含む科学の特徴ですよ
イマジネーションって言い換えればあなたの妄想ってことですよね
0903デフォルトの名無しさん垢版2021/12/08(水) 12:57:52.28ID:9TnsTyEO
データ追加の話をするのであれば、どのようなアルゴリズムでも無限個数を追加するなら無限時間かかるわw
0904デフォルトの名無しさん垢版2021/12/08(水) 13:53:27.51ID:Ji0BscRU
chaining使ってる場合でスロット数(M)が固定値かつ要素数(N)に対して小さければO(n)になるのは当然だよね

それで100点君は何を主張したいんだっけ?
0905デフォルトの名無しさん垢版2021/12/08(水) 14:37:30.67ID:Ji0BscRU
これか >>813

>また、N個のデータを持っているハッシュ構造は、1回の検索は、数学的に厳密にはO(N)
>だが、実験的(実際的)にはO(1)のように振舞うと言われており、厳密に扱うには、
>オーダーの記号だけでは表現しきれない。

「1回の検索は、数学的に厳密にはO(N)」になるのは
一般的なハッシュテーブルの実装とは関係ない架空の条件下の話だね

つかBig O記法が何の目的で使われるのか把握してなかったのか・・・
長々とお疲れさんでした
0907デフォルトの名無しさん垢版2021/12/08(水) 18:48:01.53ID:9TnsTyEO
なにを言いたいのかさっぱりわからないんだが、さかのぼって読んでみると

>>861
> 最大M個の振り分け能力があるハッシュ構造にN個の(key, value)ペアを
> 書き込んでいる場合を考える。
> ただし、Mは 定数とし、N が大きくなっても拡張していかないものとする。
> このとき、一回の検索に掛かる平均時間をg(N,M)とすると、
> ほぼ、
> g(N,M)=b・(ceil(N/(2M))

いや、全然違うし
一体何をあらわしてる式なんだ?
0908デフォルトの名無しさん垢版2021/12/08(水) 18:55:15.30ID:swPCtrVA
c++: cほど性能はいらないけど、コーティングでcより楽したい
Rust: c++くらいの性能はほしいけど、間抜けがメモリリークをエンバグするのを防ぎたい

Rustの狙いはc++&コーティング規約&lintでけっこうカバーできるけど、Rustは言語仕様としてコーダー全員に規約遵守を強制しているのが強み。
Rustが本当に普及してきたら、Rust対抗としてC++と連携できるSmartC++が出てくるんじゃないのかね。
0909デフォルトの名無しさん垢版2021/12/08(水) 19:27:33.65ID:gZbwMfFK
>>908
>Rust: c++くらいの性能はほしいけど、間抜けがメモリリークをエンバグするのを防ぎたい

これが重要だな。
0911デフォルトの名無しさん垢版2021/12/08(水) 21:56:00.76ID:tBq4QMAR
間抜けがミスをするというと十分に訓練を受けたパログラマーならミスをしないと読めるが
実際にはコードベースが大きくなると間抜けなミスをする確率が高まるので
自分はミスをしないと思い込むのではなくミスした場合も検出できるようにすべき
静的解析やrustの真価はそういうところにあると思う
0913デフォルトの名無しさん垢版2021/12/08(水) 23:45:42.27ID:s42For+c
>>911
そのためのコーディング規約&lintだろ。
極端な話、Rustみたいに
基本unique_ptrにして共有する部分だけshared_ptrを使用&生ポインタ禁止、
3rdパーティライブラリはunsafeなラッパークラスで閉じ込めた使用のみ可、
といったコーディング規約にして設計すりゃポカミスぐらいは防げる。
0914デフォルトの名無しさん垢版2021/12/09(木) 01:07:49.62ID:5YfzBk4D
>>913
何もrustに限った話ではないというのはその通りで
静的解析やrustと書いたのはそういう規約やlintで補うことも可能という意図

ただrustのshared mutabilityを原則禁じるルールなど、lintで同等のチェックするのは難しい気がする
0916デフォルトの名無しさん垢版2021/12/09(木) 08:48:29.40ID:o0+jkG0S
ポカミスってのは規約守り忘れとかも含むんだよな
lintやコンパイラみたいな機械的なチェック以外は基本信用できない
0918デフォルトの名無しさん垢版2021/12/09(木) 12:41:39.28ID:vUrE0iV7
コンパイラに強制させたいのならnext c++待ちかね。

Rustの問題点が顕在化してきたくらいのタイミングで、RustアンチテーゼとしてSmartC++とか出てくるんじゃない?

c++のバットノウハウを禁止できればRust使う必要性はずいぶん薄れるな。
「SmartC++のスコープ内では生ポインタ変数禁止」「nullのスマートポインタの生成禁止」くらいでも十分な気がしてきた。
0919デフォルトの名無しさん垢版2021/12/09(木) 14:23:33.22ID:ts6hDhJM
Lifetime ProfilerでRustのborrow checkerに近いものを実装しようとしてるけど
機能的にも未熟だし標準的に使われるレベルになるかどうかも現段階では怪しい

そんな夢見てるくらいならRust使ったほうが堅いし現実的
0920デフォルトの名無しさん垢版2021/12/09(木) 14:58:02.48ID:U+dcKQya
>>918
Rustの問題点てなんですか?
揶揄してるわけじゃなくてまだ入門の勉強中なのでいろいろ興味あります
0921デフォルトの名無しさん垢版2021/12/09(木) 17:02:43.74ID:b9s66c9I
>>920
よく言われるのが学習コストの高さ。
c++もいいかげん複雑すぎる言語と言われているけど、Rustはそれに輪をかけて難しい。
特に他の言語を勉強した初級・中級者は変数の挙動から何から違う(&他の言語のようにやるときのためのガイドラインも無い)ので地獄を見るかと。
0926デフォルトの名無しさん垢版2021/12/09(木) 18:52:37.90ID:0MvTGuxY
素直に公式のチュートリアルを流す分にはそんなに詰まるところはないと思うけどな
変に他言語の流儀を持ち込もうとするとハマりやすいというのはありそう
あといきなりWebアプリ作りたいとか思うとasyncで死ぬってのは多分ある
0927デフォルトの名無しさん垢版2021/12/09(木) 19:14:20.34ID:aTCz13pR
>>29
https://lkml.org/lkml/2021/12/6/461
ついに正式に第二言語としてとりこまれましたとさ
完璧にお前の負けやな
いいか?自分の間違えを完璧に認めて
土下座するんだぞ?
写真上げろよガイジ
0928デフォルトの名無しさん垢版2021/12/09(木) 20:04:08.95ID:Nj/MPHcu
Mac   Objective-C
Windows C++
Linux  Rust
0930デフォルトの名無しさん垢版2021/12/09(木) 20:57:13.15ID:vBwfaL6n
>>925
structとenumだけでナンでもできてわかりやすかったです
クラスや継承ピラミッドがないのも嬉しかったです
あと&selfやらderefやらその他のimpl&のおかげらしくポインタか否かを気にせず使えるのも便利ですね
0932デフォルトの名無しさん垢版2021/12/09(木) 21:02:44.54ID:aTCz13pR
自動参照外しって絶対ただの馬鹿やろ
0935デフォルトの名無しさん垢版2021/12/09(木) 21:31:04.21ID:VGbpB1xz
>>931
少し前進したな。このまま着実に進めて行って欲しい。
0936デフォルトの名無しさん垢版2021/12/10(金) 00:10:47.49ID:scZknzCz
個人開発の範囲内だとC++では困るかつRustなら上手くやれるっていうことがないから勉強する意欲があまりなかったんだが、ここまで来ると覚えとかなきゃ損なのかもな
0937デフォルトの名無しさん垢版2021/12/10(金) 00:43:14.95ID:twi4vtZr
損かどうかはともかく一度触ってみるのはいいんじゃないかな
C++書いてる時点でライフタイム周りは分かってるわけだし、結構複雑な言語機能もバリバリ使いこなせるタイプなんだからRustが合う可能性は比較的高いと思う
0941デフォルトの名無しさん垢版2021/12/10(金) 07:02:01.74ID:iN+TjAqi
C++のテンプレートメタプログラミングよりも
高い効率と抽象性をRustでも実現できるの?
だったらRust使うが
0942デフォルトの名無しさん垢版2021/12/10(金) 08:57:57.63ID:+QD/QEvI
>>941
一般的に洗脳されていると難しいけれど色んなレベルでの意識改革ができると今後に役立つよ
例えばC++自体の限界のためにテンプレートメタプログラミングでやらざるを得なかったケースがRustでは使わずに出来てしまうケースもあるし
C++ではこうやるべきだと思えていたお決まりの手法が発想を転換するとRustでは別の手法によりもっと自然に出来てしまうケースもある
一方で失敗する人たちはそういった意識改革が出来ずにC++では当たり前に思えていた方法でそのまま突き進もうとしてしまい本来は簡単に出来ることを複雑にしてしまう
もちろん能力がある人たちならばこの意識改革が出来るため必要に応じて発想の転換など臨機応変に対応することが出来ますから大丈夫
0943デフォルトの名無しさん垢版2021/12/10(金) 09:00:57.84ID:r8lQ5Qw5
>>942
> 例えばC++自体の限界のためにテンプレートメタプログラミングでやらざるを得なかったケースがRustでは使わずに出来てしまうケースもある
> C++ではこうやるべきだと思えていたお決まりの手法が発想を転換するとRustでは別の手法によりもっと自然に出来てしまうケースもある

ふむふむ。例えばどういう具体例がありますか?
0944デフォルトの名無しさん垢版2021/12/10(金) 09:49:59.85ID:+QD/QEvI
そういう気付きや意識改革を自分で出来ない人たちはもっと基本的なところからスタートすると良いかな
例えばRustにはclassすらないしtry/catch/throwすらない
C++の視点から見るとそんなのでまともなプログラミングできるの??となる
しかし現実にRustではそれらがなくとも普通に問題なく便利にプログラミングが出来ている
そして発想の転換が出来るようになるとclassやtry/catch/throwはプログラミングする上で必須なものではなかったんだなと真の理解が進む
まずはこういう基礎的なところからスタートするのがよいでしょう
0945デフォルトの名無しさん垢版2021/12/10(金) 09:55:49.46ID:PJTDipJe
type traitに関してはまんまtraitで置き換えてコンパイル時に判定できる
type traitベースでenable_ifするのはtrait boundで

テンプレートメタプロそこまで詰めてやったことないから逆にRustでできなさそうなの挙げて欲しいかも
それか両方詳しいひとカモン
0946デフォルトの名無しさん垢版2021/12/10(金) 09:58:50.45ID:kZDSpbMz
>>943
典型的なのはSFINAEを駆使してた部分がtraitで解決できるとかかな
まぁconceptと同じようなもんだけど、conceptは正直まだ発展途上だと思う
0947デフォルトの名無しさん垢版2021/12/10(金) 10:06:35.76ID:kZDSpbMz
C++はSFINAEがあるから部分的に型エラーになっても大丈夫だけど
Rustのジェネリクスはそういうのは許容しないからちょっと表現範囲は狭いね
ジェネリクスの範囲外は手続きマクロでカバーする感じ
こっちは任意のコード生成だから、テンプレートより遥かに自由度が高い(が、当然乱用するとやばい)
0949デフォルトの名無しさん垢版2021/12/10(金) 12:09:04.41ID:5non8kx0
>>948
Rustコミュニティーは若いからな。
説明ノウハウ無い&自浄作用無いので、アホがクズみたいなレスでマウント取ろうとするのは仕方ないよ。
0950デフォルトの名無しさん垢版2021/12/10(金) 12:51:44.86ID:iN+TjAqi
>>942
テンプレート機能はC++の一部だしテンプレートメタプログラミングはその機能を使ったプログラミングに過ぎない
言語自体の限界とはまったく関係ないしやらざるを得ないという表現はなにを指しているのかわからない
>>944
そんなことを言ったらRustにもプログラミング上必須でない機能が無数にあるだろう
言語間に差があることは前提で言語ごとに設計の仕方が異なるからRustの話を聞いただけだ
0952デフォルトの名無しさん垢版2021/12/10(金) 13:28:39.59ID:+QD/QEvI
>>948
あなたのコンプレックスを刺激してしまってのならばごめんなさい
嫌いになるかどうかはあなたが損するだけなのでご自由にどうぞw

>>949
単なるアドバイスがマウントに見えてしまうのは一種の病気なので
普段の生活でもマウントがどうとかそんなくだらないとこは一切気にせずに穏やかに暮らしたほうが精神面にも良いでしょう
0953デフォルトの名無しさん垢版2021/12/10(金) 13:40:16.69ID:+QD/QEvI
>>950
> そんなことを言ったらRustにもプログラミング上必須でない機能が無数にあるだろう

無数??
具体的にプログラミング上必須でない機能を挙げていただけますか?

> 言語間に差があることは前提で言語ごとに設計の仕方が異なるからRustの話を聞いただけだ

前提はおっしゃる通り同意です
具体的にどういうことをしたい時に設計の仕方でお困りですか?
0954デフォルトの名無しさん垢版2021/12/10(金) 14:37:54.35ID:xHOv0cjf
>>952
>>944がアドバイスに見えるとしたら、コーチング・ティーチング技術を勉強した方がいいよ。

>>941の「テンプレートメタプログラミング……」という問いかけには答えず、「そういう気付きや意識改革を自分で出来ない人たち」と相手を否定するだけのアホな言葉をアドバイスと言うのは無能すぎる。

こういうのはRustの害にしかならないから、>>952はアドバイスしないほうがいいよ。
0955デフォルトの名無しさん垢版2021/12/10(金) 15:03:50.43ID:+QD/QEvI
>>954
気付けない人たちへのアドバイスをしてはダメなのでしょうか?
アホな言葉とか無能とか言い出すあなたの人格を疑いますw

> こういうのはRustの害にしかならないから

こちらはRustに対して何の利害関係もなく中立なのでどうでもよいですw
むしろ害にしかならないと思い込みで決め付けることに呆れました
0958デフォルトの名無しさん垢版2021/12/10(金) 22:02:18.09ID:11uACNNS
>>941
健全なマクロはいいなぁと思った。
0959デフォルトの名無しさん垢版2021/12/10(金) 23:43:39.24ID:aT/chChl
>>955
>>954でアドバイス「技術」の話をしているのに、アドバイス「可否」の話をするのは無能の証。わかってやっているなら邪悪だし、どちらにしても>>955には他人にアドバイスする資格が無い。

やっぱりRustの害にしかならないから、>>955はアドバイスしないほうがいいよ。
0964デフォルトの名無しさん垢版2021/12/11(土) 03:13:02.46ID:gcR9gZtv
隔離スレ無いと本スレが荒れるかなって思ったけど
最近あっちは大人しいし、変なの湧き始めてからでもいいかね?
0965デフォルトの名無しさん垢版2021/12/11(土) 03:13:38.27ID:QMxo9SkC
C++もRustもそれぞれ別にスレがあるのだから次スレは要らないだろ
単発のネタスレだよここは
0966デフォルトの名無しさん垢版2021/12/11(土) 03:19:01.51ID:XUdPn4EW
冗談抜きでランダムアクセスを「乱択的に生成した要素番号の要素にアクセスすること」だと思ってる人たちが700レスくらい消費したからな
0967デフォルトの名無しさん垢版2021/12/11(土) 09:49:26.74ID:9bOVK1ul
LinkedListをランダムアクセス可能とかいうバカのおかげでスレが伸びたな
LinkedList ランダムアクセス でググれば一発で分かるようなことを延々とやってたからな
0968デフォルトの名無しさん垢版2021/12/11(土) 12:42:26.27ID:CvsP5Dh4
お互い恥ずかしいこと書いちゃったからよっぽど悔しかったんだねwww

本スレがノイズだらけになるから隔離スレは継続すべき
0970デフォルトの名無しさん垢版2021/12/11(土) 19:25:12.95ID:3cz1umgU
優秀な人はレベルの高い学校に行かないと馬鹿になってしまうということが
証明されたスレだ。
0973デフォルトの名無しさん垢版2021/12/12(日) 14:18:54.35ID:zRon8LOh
C++の場合、std::prev()、std::next()等でランダムアクセス可能。
0974デフォルトの名無しさん垢版2021/12/13(月) 04:01:27.37ID:IZffj796
それシーケンシャルアクセスや。
0975デフォルトの名無しさん垢版2021/12/13(月) 04:06:48.16ID:4QlzWvx/
std::next(v.begin(), 3)などが可能。
0978デフォルトの名無しさん垢版2021/12/13(月) 10:55:12.57ID:zBnuOauJ
ガイジ隔離できるから次スレ建てろ
0979デフォルトの名無しさん垢版2021/12/13(月) 23:41:21.78ID:hDz7sFQ7
>>758
言ってることは全く正しいけど
promise/futureの存在によってasync/awaitが成立していることをもっと強調すべきかな
このまえGoスレでそれすら理解できないやつが延々と暴れていた
さらに「async/awaitがあればpromise/futureは不要!」とまで主張して暴れていた
非同期プログラミングをかじっただけの人にありがちなのかもしれない
例えば「複数のpromise/futureに対して任意の一つが解決されたら」とか「解決順に」とかawaitだけでは表現不可能なのにな
0980デフォルトの名無しさん垢版2021/12/14(火) 01:57:04.15ID:oL+i1N1M
あわしろ氏はガイジじゃないぞ。
0982デフォルトの名無しさん垢版2021/12/14(火) 09:42:41.73ID:Lt4mRhb2
golangにasync/awaitなんて無いし、promise/futureもchannel通信で作れば作れるけどそんな事しないし
むしろ暴れてるのはお前だろ、思想的に必要無い言語にそれを持ち込んで優位性を語るなんてアホちゃうか?
0983デフォルトの名無しさん垢版2021/12/14(火) 10:15:19.20ID:YU8H/oh/
結局Rustが一番いいよな
非同期をawaitという限られた同期パターンだけでなくfutureを直接扱うことも可能だし
Goのようにコルーチンをすぐ動かせるしそれに対して同様にchannel通信もいけるしfutureとして扱うことも可能
0984デフォルトの名無しさん垢版2021/12/14(火) 10:55:30.64ID:9qJ+oS+1
アホか、Rustに厳密なcoroutineなんてデフォルトで無いやろ、Boost移植のcontext-rs/coroutine-rsとかあるけども…
実験的にRFC 2033: experimental coroutinesとかやってるけど、N:Mスレッドスケジューラーが標準搭載される未来はない。
0985デフォルトの名無しさん垢版2021/12/14(火) 11:24:57.22ID:YU8H/oh/
>>984
Rustでは一昨年からasync blockが既にstackless symmetric coroutineとして動いています
zero costでlazyなのでasync blockを作るとそれだけだとfutureが出来るのみ
それをm:n含め好きなスケジューラがいくらでもあるのでそれに対してspawnするだけで起動します
そのasync block内では全てawaitしまくればgoroutineと同じ状況になります
もちろんチャネルも使えます
0986デフォルトの名無しさん垢版2021/12/14(火) 12:31:40.21ID:cpUh/hIt
Rustの並行処理には未来を感じるけど、
tokioとasync-stdはどっちがデファクトスタンダードです?
0987デフォルトの名無しさん垢版2021/12/14(火) 12:37:47.85ID:XjtTquHZ
不毛な議論にまたなるのでアホは相手したくないが、「厳密な」と書いていることが全くわかってない。
所詮spawnするということはasync/awaitがepollベースであり、更には「全てawaitしまくれば」なんてGoと同じ状況じゃないでしょw
標準搭載と書いてるのに「好きなスケジューラがいくらでもある」とほざく
ゼロコスト、ゼロコスト言うやつがいる限りウザがられるし、英文で書けば相手を丸め込む事ができると思い込んでると
ホントに爪弾きにされるぞ、Rust推しは分かるけどもう少し顔真っ赤にしてくる態度改めようぜ?
C++でもco_await、co_yieldはゼロコストでスタック消費しないし、コンパイラ型で非同期にコスト掛かる言語って何?
0989デフォルトの名無しさん垢版2021/12/14(火) 14:53:55.31ID:nVZu9KeB
>>987
貴方のほうが色々とおかしい。

>所詮spawnするということはasync/awaitがepollベースであり、Goと同じ状況じゃないでしょw

まずepollを貴方が理解できていない。epollはLinuxでのpoll/select系システムコールのAPI。
厳密にするのも的外れなので、仮にここではselect/poll等の意味合いで受け取っておく。
Goのgoroutineも当然ながらこのselect/poll等を用いて実現しているので全く同じ状況。
当然select/poll等を用いなければgoroutineのような軽量スレッド(グリーンスレッド)は実現できない。

>所詮spawnするということはasync/awaitがepollベースであり、

引用再掲するが、貴方は更なる誤解もしている。
まず、awaitはfutureを解決する単なる一つの手段にすぎず、貴方が言及しているspawnする対象はfurureである。
そしてGoでの「go func」がRustでの「spawn(future)」に相当。
これらが為されないとどちらもスケジューラに登録されず両者は同じ状況であると言える。

>更には「全てawaitしまくれば」なんてGoと同じ状況じゃないでしょ

Goroutineでは明記しなくても暗黙的にawaitを付けたのと同じ同期的な記述で非同期を記述できる。
したがって、Rustにおいては「全てawaitしまくれば」Goと同じ状況といっても過言ではないと言えよう。
いずれにしても「go func」と「spawn(future)」の場合と同じで記述面での些細な相違だけにすぎない。

>標準搭載と書いてるのに「好きなスケジューラがいくらでもある」とほざく

Rustの標準には不可欠なものしか無いから標準搭載されていないのは当たり前。
よく例に出されるが、C言語でstdlibにあるrand()のような乱数ですらRustの標準ライブラリにはない。
貴方の無茶な理論だとRustは乱数もサポートしていない言語、となる。
OSや組み込みにも用いられる状況で、何か単一のスケジューラが標準搭載であればよい、わけがない。
むしろ様々なスケジューラを選ぶことができるRustの状況こそ、明らかに有利である。
0991デフォルトの名無しさん垢版2021/12/14(火) 16:25:41.72ID:iFoIKYew
>>989
顔真っ赤で草
0992デフォルトの名無しさん垢版2021/12/14(火) 17:27:33.19ID:YU8H/oh/
>>986
個人的には名の通りstdをasync化しているasync-stdが好みです

>>987
よくわかっていらっしゃらないようなのでどの言語でもいいから実際にプログラミングしてみることをおすすめします
epollでもselectでもいいからI/Oイベントループを自分で書いてみればそれがディスパッチャでありスケジューラの核心だとわかりますよ
C言語で大丈夫ですから
0994デフォルトの名無しさん垢版2021/12/14(火) 20:36:31.90ID:oL+i1N1M
ここまでの議論でわかったことは、RustよりGoのほうが上。
0995デフォルトの名無しさん垢版2021/12/15(水) 07:13:59.09ID:CevG0U/x
Goでできることが全てRustでもできるようになってしまったもんな
Goではできないこと辛いことが多すぎてGo2でRustの後追いしようとしているがGo2は期待外れで盛り下がっている
0997デフォルトの名無しさん垢版2021/12/15(水) 11:21:17.73ID:TZwcTz32
Goは色んなレベルで簡素で手段に制限があるけど
そこをパズルのように組み合わせてある程度のことは出来る楽しさがいいのよ
ただしそれが飽きられてきていたり楽しいと思う人たちより外に広まらなかったり
自然じゃない組み合わせで実装や冗長な記述などせざるをえなかったり
だからGoはこのまま狭い適用範囲だけで使われる形になりそう
0998デフォルトの名無しさん垢版2021/12/15(水) 11:41:54.42ID:z10T13Tn
このスレなくなったら名残惜しいから次スレ建てろ
完走しても建ってなかったらワイが建てるで
0999デフォルトの名無しさん垢版2021/12/15(水) 12:34:06.40ID:t4BO72er
>>997
納得できない
じゃあきみはGoにGenericsとか実装されても使いたくないの?

Goの良いところはそういうとこじゃないでしょ
1000デフォルトの名無しさん垢版2021/12/15(水) 12:34:55.45ID:z10T13Tn
1000ならC++の勝ち!!!!!
10011001垢版Over 1000Thread
このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 235日 4時間 30分 6秒
10021002垢版Over 1000Thread
5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。


───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────

会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。

▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/

▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php
レス数が1000を超えています。これ以上書き込みはできません。

ニューススポーツなんでも実況