C++ vs Rust

■ このスレッドは過去ログ倉庫に格納されています
2021/04/24(土) 08:04:49.48ID:nPKzA798
競え
2021/11/22(月) 17:48:40.73ID:43z4eYfr
「Rustだとできない」っていうのはよくわからないし、そこだけ気になってるんだけど、
Rustって参照を持ち回すことがそんなにできないんだ
2021/11/22(月) 17:49:16.27ID:EEj8G+es
C言語であろうがなかろうが言語に関係なくO(1)は無理
わからない人はコーディングすればすぐわかる
ランダムでkが与えられた時にリンクリストのk番目を常にO(1)で得るためには
全てのk番目の位置を別の配列で保持管理しないといけない
そしてリンクリストで挿入削除が行われるたびにk番目がズレるから保持管理する配列で毎回O(n)を必要とする移動が発生
どんな言語でどんな手法を用いてもO(1)は絶対に不可能
2021/11/22(月) 17:53:40.47ID:ejqG4gpN
>>198
俺もそう思う
彼の主張にはポインタの配列をケアする時間を含んで無さそうに聞こえたけどw
せっかくのリクリストとは別にアクセス用のポインタ配列をケアするってことも
ふしぎなコーディングだけど
そこまでするなら最初から配列だけでやれって思うけどw
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回行っても同じ。

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

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

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

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

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

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

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

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

なんで、このスレはこんなにレベルが低いの。
2021/11/22(月) 19:21:28.08ID:HWCOZSD4
>>230
>そんなウソをついて何がしたいのかさっぱりわからない
真実だから。
2021/11/22(月) 19:27:10.84ID:DZQ1+JmR
>>232
数学の専門家であってプログラミング経験がないからソースコード出せとの指摘には一切答えられないということかな
2021/11/22(月) 19:32:17.29ID:fRCpO7Rh
>>194
ここであなたがおっしゃっているのは、以下のような実装のことでしょうか?

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

lnはリストのn番目の要素
2021/11/22(月) 19:43:59.25ID:HWCOZSD4
>>234
近いが、初期値が、{ &l5, &l1, &l123, &l25, ... };
のようになっているイメージ。
ただし、実際には、
・初期化子リストには書かず、プログラムの途中でリンクリストに挿入した直後に記録するような
 ことが多い。
・ノードの識別を常にポインタで扱うので、& で書くことは無い。
・固定配列ではなく、それもまたリンクリストにすることが多い。
 なぜなら、リンクリストは効率が良いことが多いから。
2021/11/22(月) 19:46:52.11ID:HWCOZSD4
>>233
そうではなく、
・大規模すぎて、こういうところには抽出して書ききれない。
・言葉で書いたほうが理解し易いはずだと思った。
 抽象概念を理解しにくい人がこんなに多いスレだとは思わなかったから。
・しかし、これだけ書いても理解できないと言うことは、具体的に書いても
 ますますそのコードの本質的な意味が理解できないと思われる。
2021/11/22(月) 19:57:10.45ID:43z4eYfr
中国共産党のお偉いさんって本当に偉いんですね
2021/11/22(月) 19:57:37.97ID:43z4eYfr
スレ間違えた まいいか
2021/11/22(月) 20:02:20.61ID:fRCpO7Rh
>>235
ある要素が複数のリストに所属するイメージでしょうか
例えば全要素が連なっているリストのn番目、特定の要素だけが抽出された別のリストのm番目に属すといったような
要素の削除に当たっては属するすべてのリストについて前後の要素からの参照を外す
2021/11/22(月) 20:03:50.15ID:5egSOJea
配列でもリンクリストでも他のコレクションでも全てに言えること
「格納要素が『データ本体でも、ポインタでも、何らかのid番号でも、他のインデックス番号でも、』そこは一切関係なく、様々な操作のオーダーOが変わることはない」
まずこの大原則をID:HWCOZSD4は理解できていないのたろう
だからポインタを使うと魔法のようにオーダーがO(1)になると勘違いしている
2021/11/22(月) 20:04:15.63ID:HWCOZSD4
>>239
今回例としてあげたのはそういうケース。
ただそれは一例であってさまざまなケースがある。
2021/11/22(月) 20:04:48.66ID:HWCOZSD4
>>240
アホか。
俺は現実世界では天才と言われてるのに。
2021/11/22(月) 20:05:43.93ID:fRCpO7Rh
>>241
この一例もやはりRustでは実装できないのでしょうか
244デフォルトの名無しさん
垢版 |
2021/11/22(月) 20:07:17.81ID:HWCOZSD4
>>243
読み込みオンリーに限定して、一切削除もしないという条件なら可能。
ノードの中に書き込んだり、ノードを削除するなら、不可能。
2021/11/22(月) 20:08:42.39ID:HWCOZSD4
>>244
[補足]
C/C++/Java/C#/JS/Ruby/Python など多くの言語では可能だが、Rust
だけが不可能。
なので、Rustだけが仲間はずれであり、他の言語でできる事ができない。
2021/11/22(月) 20:10:06.74ID:5egSOJea
>>243
C言語で可能なことはRustでも可能

>>244
嘘つき
2021/11/22(月) 20:11:54.24ID:4Q+A1yLL
>>236
gistでもどこでもいいからコード貼り付けてリンクここに貼ってください
日本語でうだうだ話すより議論が早く終わるでしょうあなたの言うことが正しければ
2021/11/22(月) 20:14:36.47ID:EEj8G+es
>>245
Rustでプログラミングをしたこともない人がデタラメな妄想を撒き散らしてるなw
2021/11/22(月) 20:14:53.48ID:HWCOZSD4
>>246
デタラメ一言ってんじゃないぞ!!

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

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

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

とか言ってても狂人扱いされるだけに決まってるじゃん・・・
2021/11/22(月) 20:29:18.57ID:0LbM6y2O
Cursorを使えと何回言っても聞かない
テキストエディタの例では>>119のアイデアを完全無視
2021/11/22(月) 20:50:09.64ID:MtEs+7mt
おれも興味があるな
C++では書けてRustでは書けないコード

リソースを無視すればチューリング完全だろうから
書けないなんて事はないはずで
何かしら制限を付けた上での「書けない」なんだろうけど
2021/11/22(月) 20:55:11.07ID:fRCpO7Rh
>>245
Rust でも書けるように思えてしまったのですが、以下のコードはどこが間違っているのでしょうか

https://play.rust-lang.org/?version=stable&;mode=debug&edition=2021&gist=7534885705cd5879f536acdf64947870
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 }]
}
2021/11/22(月) 21:13:26.74ID:7gi7NmEv
>>255
Cursorでも無理だ。
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 }]
2021/11/22(月) 21:17:24.64ID:DZQ1+JmR
Rustの実装 (>>257) はポインタでの直接アクセスではなく配列への添え字アクセスだからオーバーヘッドが大きいとか言い出したらみんなで笑ってあげましょう
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;
}
2021/11/22(月) 21:27:13.68ID:7gi7NmEv
>>261
ゼロコストが謳いなのに、ゼロコストで無い。
2021/11/22(月) 21:27:14.40ID:5egSOJea
>>257
それで実装も動作も良いけど
_bはどちらも不要
_a.0と_a.1はそれぞれprevとnextと書いたほうが読みやすい
2021/11/22(月) 21:33:11.94ID:fRCpO7Rh
>>264
_b は単一の要素が複数のリストに属するという要件に対する実装ですね
面倒だったのでメンバーだけ用意して実装はしてないですが
タプル使ってるのも構造体定義が面倒だったため
というかできるできないを実証するための例なので細かいところは適当です
お好きなように修正してください

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

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

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

またアロケーションについてはVecを実装が工夫されたコンテナ型に変えることで対応できそうですね
実装詳細のないまま議論してもしょうがないトピックなのでこれ以上こちらからレスを重ねることはやめます
ありがとうございました
2021/11/22(月) 22:10:00.62ID:7gi7NmEv
>>271
[追加]
3. そこにさらに削除メソッドを実装したとしよう。
 削除したノードに対する番号が、どこかのCursorの中にまだ生きた状態に
 なっている場合、ダングリング参照と似た現象が起きる。
 削除したノードの中を参照できてしまうのだ。
2021/11/22(月) 22:15:27.68ID:7gi7NmEv
>>273
その主張、Rustの中に超軽量のインタプリタの様なものを載せておいて、
そのインタプリタの中ではランダムアクセスがO(1)のリンクリストが
完全に実装できることを示しただけだね。
しかも、追加すると、時々、大規模なメモリーコピーが生じるし。
newやmallocではそのようなメモリーコピーは生じない。
ノードを追加しても、リンクリスト中の他のノードの本当のマシン語レベルでの
線形アドレスが固定で変化し無いし。
あなたの実装では、それが変化してしまう。相対アドレスは変化しないが。
ベースアドレスが変化している。
2021/11/22(月) 22:19:00.36ID:fRCpO7Rh
>>274
generational arenaという手法を利用することでダングリングポインタ的アクセスを検知してハンドリング可能になります
2021/11/22(月) 22:19:03.44ID:7gi7NmEv
>>274
[補足]
実質的なダングリング参照が起きるということは、Rustのもう一つの柱である
ところのメモリー安全性が部分的に壊れてしまってるということだ。
2021/11/22(月) 22:23:12.75ID:7gi7NmEv
>>276
動的コストを掛けていいなら、C++でも安全性の高いものは作れるぞ。
ポインタも正しいメモリーブロックを指していることを動的に確認した後で
実際に参照するようなことは、C++でも出来るから。
Rustも配列の範囲チェックはやっているが、配列以外のアドレスでも、動的に
チェックしようと思えばいろいろなチェック法はある。
その一つの方法が、アドレスではなく、あなたが書いたような配列の中の
番号方式にしてしまうこと。
番号に対する配列要素がNULLになっていれば、動的にエラーを出力して
アプリを停止させる、などの方法が有る。
2021/11/22(月) 22:25:32.33ID:fRCpO7Rh
>>278
Rustの zero-cost abstraction はあなたの期待するような物ではありませんでした
残念でしたね
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も標準のものとは別。
2021/11/22(月) 22:37:35.24ID:0LbM6y2O
結局何がしたいのよ
ノードへの参照を持ったままリストを変更したいの?
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++の実装に比べて速度的に不安定でありスパイク的に
遅くなるということだ。
2021/11/22(月) 22:51:04.06ID:0LbM6y2O
>>282
「LinkedListへのアクセスがO(1)で自由自在に出来る」
が正確にはどういう意味かと聞いているんだ

>>257の実装は忘れなさい
2021/11/22(月) 22:52:27.47ID:7gi7NmEv
>>281
>ノードへの参照を持ったままリストを変更したいの?
もちろん、それもある。
2021/11/22(月) 22:56:03.63ID:qBbb57Hy
デマを流すのはゼロコストなんだから相手にした時点で負け
286デフォルトの名無しさん
垢版 |
2021/11/22(月) 22:57:09.11ID:7gi7NmEv
>>283
>「LinkedListへのアクセスがO(1)で自由自在に出来る」
>が正確にはどういう意味かと聞いているんだ

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

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

実際に、今回の実装を示した彼は、俺の言ってることはある程度正しく理解していた。
つまり、基本的にデマじゃないということを理解した人がいるということだ。
ただし、彼は、ゼロコスト安全性である、ということを無視して独自実装したり、
参照を独自に修正したものを勝手に導入した誤魔化しがあったのが残念であった
だけだ。
つまり、俺の主張自体は、彼は本当は理解している。
理解しているが、悔し紛れに詐欺めいた独自実装をしたことだけが残念なだけだ。
2021/11/22(月) 23:01:57.98ID:7gi7NmEv
>>288
1つのリンクリストに対して、書き込み参照や読み込み参照を同時に複数持てない。
2021/11/22(月) 23:13:17.79ID:5egSOJea
>>290
デマを流すのはそろそろやめとけよ
RustはRefCellもあるし複数からポインタで指しつつ書き換えもできるぞ
2021/11/22(月) 23:14:41.21ID:7gi7NmEv
>>291
そもそも、RefCellは、動的チェックが入るからゼロコストではない。
C には存在しないコストが新たに導入される。
2021/11/22(月) 23:15:37.93ID:WXoW4mOX
unsafe で生ポインタ使えばCと同じ実装は確実にできるが
294デフォルトの名無しさん
垢版 |
2021/11/22(月) 23:15:41.59ID:NDd1353W
リンクトリストな?
2021/11/22(月) 23:16:05.08ID:5egSOJea
>>292
何を言ってるんだ?
そういうコストかけずにどうやって排他制御するんだよ?
2021/11/22(月) 23:18:27.46ID:WXoW4mOX
>>295
そこはCだとプログラマが気をつけることで排他制御してるんだと思うよ
unsafe Rustでも同じだけど
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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