◎正当な理由による書き込みの削除について: 生島英之 とみられる方へ:Rust part27 YouTube動画>1本
動画、画像抽出 ||
この掲示板へ
類似スレ
掲示板一覧 人気スレ 動画人気順
このスレへの固定リンク: http://5chb.net/r/tech/1733146370/ ヒント: 5chスレのurlに http ://xxxx.5chb .net/xxxx のようにb を入れるだけでここでスレ保存、閲覧できます。
>>3 何年も更新されてない上に誤訳だらけの非公式翻訳を貼り続けるのいい加減やめろ
前スレの「変数束縛」とか含めて非公式翻訳が勘違い野郎を生む諸悪の根源
はいはい、説教おじさんはほっといて気楽に質問してね~。勘違いでもなんでもok。サンプル欲しければコード書きますよ~。
日頃GC付き言語で開発しているからメモリリークがどういったプログラムで起こるのかあんまり実感できない C言語で書かれたプログラムでメモリリークしやすいプログラムってどんなもんなの?
>>8 最近のPCはメモリたくさん積んでるから、リークしても気にしなくていいよ
メモリプレッシャーがかかっても不必要にメモリをつかみ続けるFirefoxのようなお行儀の悪いプログラムか増えてるからメモリが潤沢にあってもリークは気にしたほうがいい 使い捨てプログラムや低品質でもいいプログラムなら気にしなくてもいいけどそういうのはGC言語でやる
>>8 仕事の製品開発ならgc言語でもメモリプロファイラ一使えよ
ハードの性能向上を無駄に消費するクソソフト多すぎだろ
GC 付きでもメモリリークのようなことが起こることはある。
多くの場合に表面化しないだけ。
プロセスが終わるときにはどうせまるごと回収されるからガッと処理してすぐ終わるようなプログラムでは特に表面化しにくい。
見えにくいからこそ意識的に調査すべきで、
>>11 の意見に同意する。
逆に問題が表面化しやすいのは長期的に起動しっぱなしなもので、わかりやすい例ではウェブサーバ (またはその後ろでサービスを提供するプログラム) などが挙げられる。
ウェブサーバの H2O はそれを防止するのと高速化のためにセッションごとにメモリの塊を確保してその塊の頭から順番に使っていき、セッションが終わると塊をまるごと解放するというメモリ戦略を取ってる。
C言語でリークという話なのでこんな感じ。 // メモリリーク例1: mallocした後にfreeし忘れる関数 void leak_in_function() { char* ptr = (char*)malloc(100); strcpy(ptr, "Hello"); // freeがないのでメモリリーク } // メモリリーク例2: 条件分岐でfreeを飛ばしてしまう void conditional_leak(int value) { int* numbers = (int*)malloc(sizeof(int) * 100); if (value < 0) { return; // ここでreturnするとfreeされない } // 処理 free(numbers); } // メモリリーク例3: ポインタの上書きによるリーク void pointer_overwrite() { char* ptr1 = (char*)malloc(50); ptr1 = (char*)malloc(100); // 最初のメモリブロックへの参照が失われる free(ptr1); // 2番目のメモリブロックだけがfreeされる }
// メモリリーク例4: 動的配列の不完全な解放 typedef struct { char* name; int age; } Person; void struct_array_leak() { Person* people = (Person*)malloc(3 * sizeof(Person)); for (int i = 0; i < 3; i++) { people[i].name = (char*)malloc(50); strcpy(people[i].name, "John Doe"); } free(people); // name用のメモリがリークする } こういうパターンが多いかな。 C++だと生ポインタ使わなくなるので大分解消されるけど。
バグが0になるまで投資を続けるのは誰もやらないのに メモリリークを0にしようって言われたら投資してしまうのが人情というものだ
>>8 ここはRustスレなのに
なぜRustについて全く触れずにC言語の質問をするの?
C言語のスレがあるのだからそちらでしなさい
Rustについて触れずに他の言語の話だけをしている人たちも同罪
必ずRustについても言及しなさい
Rustのメモリ安全性の目的はメモリリークの回避じゃなくてダングリング参照の回避定期 ついでに競合アクセスも防ぐ
C言語はfree()しても断片化という問題が発生すると聞いたことがある 断片化してもOSが落ちたりはしないんだろうけど遅くなるとかならないとか・・・
>>19 断片化によって起こるのはメモリ効率の悪さ。
空いてるメモリの総量が充分にあっても必要分だけ連続したメモリがない(メモリ確保に失敗する)ということが起こる。
C では確保したメモリの場所が変わる(アドレスが変わる)ということは起すわけにいかないので断片化はそれなりに深刻な問題になりうる。
GC には copying gc のように不要メモリの回収と同時に再配置するものもある。
64bitのアドレスが枯渇したとして・・・全オブジェクトに印をつけるGCを使うか?
Rustは長時間動かすとメモリが断片化するから、サーバープログラミングに向いてない
https://www.publickey1.jp/blog/22/cloudflarenginxrusthttppingoracdncpu31.html CDN世界トップシェアのCloudflareは、同社のグローバルなCDNの基盤として長らく利用してきたC製のNGINXに代えて、
Rust製のHTTPプロキシサーバである「Pingora」を開発して利用していることを明らかにしました。
Pingoraはすでに同社のCDNに採用され、毎日1兆回以上のリクエストを処理し、性能向上や数多くの新機能の提供を実現しており、
従来のNGINXと比較してCPUとメモリリソースの消費はいずれも3分の1程度に収まっているとのこと。
今時の標準アロケーターはよほどでかい領域を確保しない限りメモリの断片化は起きないようになってる。それでも問題ならカスタムアロケーター書くよ。
アマゾンのAWSもRust製 Webサーバサイドでリソース節約したいならRust一択
>>10 現代的には使われていないメモリがあるほうが「無駄がある」と考える思想なので、メモリはあればあるだけ使う(キャッシュやプリロードなど投機的な処理で体感的な速度を上げる)設計になってる。
本当に足りなくなるまでは掴んだままのほうが良いと判断してやってる。
現代のニーズに合わせた意図的な設計としてやってるのでリークとは違う。
良いか悪いかは知らんがリークとは違う。
Rustはいつメモリのコンパクションできるようになるの?
いつも渋滞している道路は無駄がない道路か まあ徒歩より遅いなら燃料いらないからな
>>26 メモリ足りなくなったから不要なメモリ掴んでたら解放してくれと
OSからのメッセージが出ても掴み続けてるアプリが結構あるので
メモリが潤沢にあるからといってリークは気にしなくてもいいなんていう心構えでプログラミングしたらダメだぞという話
難しい話じゃないと思うんだけど1回で伝わらないのは悲しい
サーバでもアプリでもその他でも プログラム起動中ずっと必要になるデータは leak()して&'staticにしてしまっても構わない これはメモリリークではない 一方ですぐ不要となるデータはleak()してはいけない これはメモリ使用量が増えていってメモリリークになる この違いをきちんと認識した上でleak()を活用しよう ずっと必要になるデータを&'staticにできる大きなメリットがある
FireFoxのメモリリークは本当に酷い Rust使ってるっていうのは嘘だろ
>>32 そこはC++コード
FireFoxでRustを使っているのはHTML/CSSレンダリング部分
メモリ管理部分を含めてメインはC++で記述されている
ソースが公開されているので誰でも確認できる
リークしてるんじゃなくて意図的に解放してないだけ 本当にやばくなったら解放されるようになってる メモリ食いが嫌ならAuto Tab Discardアドオンを入れろ
>>31 それを普及させて何がやりたいのか分からなかった
が「やりたいことと合致しない現実」を報道する自由を欲しているらしいと最近分かった
もし仮に特定のアプリに問題があったとしても それはC++やRustの言語の問題ではない このスレで特定のアプリの問題の話を始める人は愚か
>>33 何でいつまでたってもRustで書き直さないんだろな
>>30 主旨に反論したわけじゃない。 Firefox が例として不適当と言ってる。
Firefox は貪欲にメモリを使うが本当に足りなくなる手前で抑制的なモードに切り替わる。
Windows からメモリ不足のメッセージを出したときに Firefox がメモリを掴んだままなのは手放せるものは既に手放してるからだ。
メモリ不足になったときは本当にメモリ不足なんだよ。
FirefoxもChromeもその他のブラウザもやっていないが 究極的にはアクティブウィンドウのアクティブタブ以外の全ての使用メモリを原理的には解放できる どの方針を採るにしてもC++やRustといった使用言語の問題ではなくどの言語でも可能だ 明らかにスレ違いの話題だから他のスレでやってくれ
tab閉じてもそのtabが使ってたメモリ解放しないんじゃリークだろ
>>40 長く表示していないタブを一旦解放する仕組みが導入されたこともあるんだが思ったより問題が大きくて消極的になった。
コンテキストの管理とレンダラは不可分な部分もあるので再レンダリングに必要な情報を残しつつ他は解放するってのは手間がかかって割に合わないと考えられてる。
>>41 閉じた時じゃなくてアクティブタブじゃなくなったときの話を
>>40 はしてるのにそれがわからないなら黙ってろ。
モダンなブラウザはプロセスを分離しまくっていてプロセス間通信で協調する仕組みになってる。
タブひとつ (または数個のグループ) に対応するプロセスがあって適当な条件でプロセスごと消えて作り直されたりするので仮にメモリ管理に多少の問題があっても全体の堅牢さは維持される。
>>39 >Firefox がメモリを掴んだままなのは手放せるものは既に手放してるからだ。
これは嘘
単にお行儀が悪いだけ
>>40 >FirefoxもChromeもその他のブラウザもやっていないが
Safariは閉じたタブのメモリはもちろんのこと
長く非アクティブなタブのメモリは割と積極的に解放してる
いずれにしても各アプリのレベルのメモリ管理の話であってプログラミング言語と関係がない しかもFirefoxのメモリ管理部分はC++で記述されている ここRustスレで無関係な話をいつまで続ける気だ
>>39 >主旨に反論したわけじゃない
いやいや主旨を理解してないのに主旨に反論してるもしてないもあるかいな
ふむ、広告ブロックを強化すればメモリ節約できるのでは
循環参照が起きやすい場面の一つだし、これこそプログラミング言語の仕様と関係のある場面じゃないのかな
Webページ毎に別なので アリーナ的管理により循環参照があろうと一気に解放するためリークが起きようがない
メモリリークと脆弱性の混合物なら急を要するが完全に分離されたから意識低くなった
>>48 悪いっていうより、自由が利きやすいんじゃない
iterator traitのnextでiteratorの中のデータの参照を返すことがどうしてもできません 教えてください
>>53 lending iteratorでググるといい
// まず、データを保持する構造体を定義 struct DataHolder { items: Vec<String>, } // イテレータ構造体を定義 // ライフタイムパラメータ 'a を使って、参照の寿命を明示 struct DataIterator<'a> { data: &'a DataHolder, // データへの参照 index: usize, // 現在の位置 } // DataHolderにイテレータを作成するメソッドを実装 impl DataHolder { fn new() -> Self { DataHolder { items: vec![String::from("one"), String::from("two"), String::from("three")], } } // イテレータを返すメソッド fn iter(&self) -> DataIterator { DataIterator { data: self, index: 0, } } }
// Iteratorトレイトの実装 impl<'a> Iterator for DataIterator<'a> { // 返り値の型を&'a Stringと指定 type Item = &'a String; fn next(&mut self) -> Option<Self::Item> { if self.index < self.data.items.len() { let item = &self.data.items[self.index]; self.index += 1; Some(item) } else { None } } } // 使用例 fn main() { let holder = DataHolder::new(); // イテレータを使用 for item in holder.iter() { println!("{}", item); } } やりたいことはこんな感じ?
こんな感じです struct It<'a>{ i: &'a mut i32 } impl<'a> Iterator for It<'a>{ type Item= &'a i32; fn next(&mut self)->Option<Self::Item>{ Some(self.i) } }
iter()が作りたいのか、iter_mut()が欲しいのかどっちかな? あとこれだと無限に続くイテレータになるけど終了条件は?
struct It<'a>{ i: &'a mut i32 } impl<'a> Iterator for It<'a>{ type Item= &'a i32; fn next(&mut self)->Option<Self::Item>{ self.i+=1; Some(self.i) } } こんな感じなのでmutはいります 本当はiter_mutが作りたいけれど難しそうなので iterを作ろうとしたけれどどうしても出来ません 初心者です教えてください
結局毎回同じ参照返すならイテレータじゃなくてよくね
自分の可変参照を返したいならGATでこうする use lending_iterator::prelude::*; fn main() { let mut v: Vec<String> = ["a", "b", "c", "d", "e"].into_iter().map(str::to_string).collect(); my_iter_mut(&mut v) .skip(1) .take(3) .for_each(|s| s.push('x')); assert_eq!(v, ["a", "bx", "cx", "dx", "e"]); } fn my_iter_mut<'a, T>(slice: &'a mut [T]) -> MyIterMut<'a, T> { MyIterMut { slice, index: 0 } } struct MyIterMut<'a, T> { slice: &'a mut [T], index: usize, } #[gat] impl<'a, T> LendingIterator for MyIterMut<'a, T> { type Item<'next> where Self : 'next = &'next mut T; fn next(self: &'_ mut MyIterMut<'a, T>) -> Option<Item<'_, Self>> { if self.index < self.slice.len() { self.index += 1; Some(&mut self.slice[self.index - 1]) } else { None } } }
>>65 自己レス
即興で作って冗長な表記があったため
next()関数はこれで
fn next(&mut self) -> Option<Item<'_, Self>> {
(self.index < self.slice.len()).then(|| {
let nth = &mut self.slice[self.index];
self.index += 1;
nth
})
}
>>61 next()で返された不変参照r1(&i32)が生きてる間に次のnext()が呼ばれたら
r1の参照先の値が変わることになるからこの形はIteratorだと実現できないな
同じ値に対する&Tと&mut Tが共存できないルールに引っかかる
next()の戻り値にIt自体のライフタイム(&'b mut selfの'b)を含めて
戻り値の参照が存在してる間は次のnext()を呼べない形にしないといけないけど
Iteratorはそういう制限を想定してない
Vecなどを作れて逆順にもできるイテレータとは性質が異なる 異なるものを、どっちも同じだと頑なに主張し続ける必要はない気がする
67は一般的なイテレータの概念じゃなくstd::iter::Iteratorの話 このtraitを実装すると例えばIterator::max()も自動的に使えるようになるけど この実装はSelf::Itemの暫定の最大値を保持しながら次のnextを呼ぶ必要がある 前の値を解放しないと次のnextを使えない状態だと std::iter::Iteratorが使用者側に保証してる条件を満たせないし 安全なコードの範囲でimpl Iteratorのコンパイルも通せない 自前のIteratorトレイトを用意してもいいけど それだとstd::iter::Iteratorが要求される処理には使えなくなる
>>68 Vecを作れるのも逆順も全て別の話
それぞれ別の要件を備えていないと一般的なイテレータではどちらも不可能
例えばイテレータ「1..」はVecを作れない&逆順に呼ぶのも無理
std::iter::repeat(1)はVecを作れないがDoubleEndedIteratorを実装しているのでメソッドrev()が使えて逆順に呼べる!
自己可変参照を返す
>>65 のMyIterMutはスライス&mut [T]を内部に持っているため逆順呼び出しrev()メソッドの実装が可能
>>69 そのmax()は自動的に全てのイテレータに使えるわけではない
Self::Itemがstd::cmp::Ordを実装している時のみ使える
前の値を保持したままにできるか否かの性質についてもmarker traitを用意することで同じ枠組みに組み込めた可能性がある
それを出来ていないのがstd::iter::Iteratorの欠陥なので他を併用するのがRustでは当たり前になっている
イテレータの前の値を保持できるか否かのどちらが優れているかといえば より効率的な機能を提供できる点で「前の値を保持できない」方が優れた機能を提供できる 例えばstd::io::BufReadのlines()を考えてみよう 毎回新たなStringを返してくるので前の値を保持できる仕様となっている しかしlines()の利用で前の値なんて不要なことも多いからその観点からは無駄な仕様ともいえる 一方で「前の値を保持できない」性質にも対応出来ていたとしたら同じStringを使い回すことが出来て明らかに効率が良い このような例は多数あり自己参照返しイテレータが別途必要とされて使われている理由である
>>70 長さが有限でも実行時にメモリが足りなければVecもreverseもないけど
「実行時に」という要件は備えなくて良いというルールがあるんだよね?
61(初心者)が実現できないimpl Iteratorで詰まってるんだから できない理由を分かってもらうのが優先でしょ イテレータの優劣とか代替案はその後でいい
>>73 rev()メソッドのtrait DoubleEndedIteratorはゼロコスト抽象化
逆順に並べ替えることはしないのでそのためのメモリは必要ない
既にある任意の構造を後ろからたどる、あるいは、後ろから計算するだけ
>>74 それならば別の条件が必要となるIterator::max()を事例に出すのはよろしくないかな
説明するためには単純にこれだけでいいよ
let first = iter.next();
let second = iter.next();
println!("{first:?} {second:?}");
>>76 next2回呼ぶだけだとstd::iter::Iteratorと関係なくなるだろ
自分がそういう使い方をしなければ問題ないってなるだけ
maxはstd::iter::Iteratorの実装に求められる条件の分かりやすい例として挙げた
別の条件まで気にするならmax_byでもいいけどそれはそれで初心者には余計なノイズが増える
コピーもcloneもできないデータの存在自体がノイズだね 本当はcloneできるんだけどゼロコストではできないとか言ってるのもノイズだ
>>67 stdのIterator::nextの&mut selfのライフタイムはnextメソッドを抜けるところまで
(次のnextが呼ばれるまで生きてない)
つまりstdのIteratorでは&mut selfのライフタイムに依存するような参照を返すことはできないということ
そういう参照を返したいならlending iterator
逆に言えば&mut selfのライフタイムに依存しない参照であればstdのIteratorでも返せるということ
>>77 max_byも同じ
Ord実装型そのものかOrd実装型に変換してOrd::cmp()できる時のみ利用できる
それらを持ち出さなくてもSelf::Itemの条件なくcollect()すなわち収納型へのFromIteratorが適用される
つまりfirst要素とsecond要素が同時に存在することになると矛盾の説明で十分となる
そのため自己参照を返すイテレータはstd::iter::Iteratorがカバーする範囲になく別途必要となる話をしてきた
>>78 イテレータが返すのはデータ値自体とは限らず参照も返す
特に今回の質問者が返したい可変参照は明確に!Cloneが定義されていてもちろん!Copyでもある
それでも可変参照をイテレータが返すことができてVecへ収容することも可能なのはCloneもコピーも行われないためだ
さらにそれらと全く独立した話としてイテレータ自体への参照/可変参照を返す場合はstd::iter::Iteratorで扱えないためLendingIteratorを使うという話が本題
そんなに移動がしたいならこれでいい first = into_next(iter); // iterはもう値を所有しない second = into_next(first) // firstはもう値を所有しない
>>83 それによって新たにできるようになることや新たに生じるメリットは何?
C++でもRustでも変わらないメリットはcloneとdropをしなくてすむことだが そういえば、Rust固有のメリットは'aが出てこないことと 'staticも出てこないことだな
全然話変わるんだけどPinky Crush新曲のlowercase lifetimeってRust関係あるのかな
>>61 mutでないiterも出来なくて困ってるとのことなので
スライスのiter()と同じものがLendingIteratorを使わずに書けるよ
struct MyIter<'a, T>(&'a [T]);
fn my_iter<'a, T>(slice: &'a [T]) -> MyIter<'a, T> {
MyIter(slice)
}
impl<'a, T> std::iter::Iterator for MyIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if let [first, rest @ ..] = self.0 {
self.0 = rest;
Some(first)
} else {
None
}
}
}
fn main() {
let a = ["foo", "bar"];
let mut iter = my_iter(&a);
assert_eq!(iter.next(), Some(&"foo"));
assert_eq!(iter.next(), Some(&"bar"));
assert_eq!(iter.next(), None);
}
組み込みFW屋さんなんだけどRustやってみようかな… 組み込み屋視点でRustはC++の何を解決してると思う? 組み込み屋なんて古いシステムばかりだからすぐに取って代わることは無いとは思うけど 年々複雑な製品を求められるから選択肢としては持っておきたい
>>88 ダングリング参照を発見出来るだけ……とは言えそれが重要ではあるのだけど。
C++ は結局は人が気を付けなきゃならないことだらけで、複雑になると手におえない。
知ってることでも複雑に絡み合った状況では間違う。
C++ よりは機械的に検証可能な範囲を広げてるだけでもありがたいものだよ。
>>90 え?マジ?
俄然興味湧いてきた
さっさと定時で帰って環境整えるか
ビット幅気にするようなケースだと 数値型の暗黙の型変換がないとか演算時のオーバーフローの扱いを明示的に書けるとかが結構ありがたい
科学 + 5ch
【AI】AIはわずか2時間の対話で人間の性格をコピーできる [すらいむ★]
http://2chb.net/r/scienceplus/1733576027/ コメントに面白いことが書かれている
>>92 たしかに基礎的なことではあるがC/C++ではうっかり数値型の自動キャストでハマることもあるし
何よりも未定義動作が多くてこれも沼にハマる原因だな
それらを無くしたRustは賢明だ
struct RefMutex<'a, T>(&'a Mutex<T>); impl<'a, T> Iterator for RefMutex<'a, T> { type Item = std::sync::MutexGuard<'a, T>; //略 } try_lockが失敗したらループが止まります マルチスレッドならランダムに止まります 知らんけど
FnMut() -> Option<T>っぽいあらゆる処理を全部Iterator化しようという気概を感じるな 近寄らんとこ
イテレータが勝手にループすることはない ループするよう別途コードを書かなければならない Option<T>を返す関数をfとすると while let Some(x) = f() { ... } で十分である つまりイテレータ実装する意味がない イテレータメソッドに繋げたい!という反論もあろう それなら std::iter::from_fn(f) で十分である
Iteratorの話は、lifetimeの棍棒で殴られたという文脈で出てきただけだな 構造体のメンバーが&'a Mutex<T>なら reborrowではなくmoveで取得した値に対しderef_mutが使える moveなら殴られない
>>88 c++使ってる組み込みって組み込みLinuxとかじゃねーの?
あんまり組み込み特有の制限ないだろ
好きに組めや
これはポリシーというか戦略が違ってて、「今より少しでも改善するなら採用」だからじゃないかと 従来型の「最低限のクオリティに達するまではreject」へのアンチテーゼでもあるから そして(文句あるかもしれんが)crates開発者は元々のエンジニアの質がそこそこ高かったからそれでも何とかなったものの、 同じ事をGitでやったからあの「ぼくがおもいついたすごいcrates」の山になったのだと思う 交通整理すらやる気無かったわけだ とはいえ、「使われなくなったcratesは、いつしか動かなくなった事すら認識されなくなり、死んでいく」という、 Gitコマンド内でのライフゲームをやるつもりなら、ありなんだろうさ
読み終わった
>>102 具体的なアプローチは以下の通りである:
(1) 段階的なRust導入:
略
(2) 既存のCコードベースとの統合:
略
(3) ベアメタル環境への対応:
略
(4) ビルド最適化とパフォーマンスの考慮:
略
Rustで連番IDを発行する関数はこれでいい? fn new_id() -> Option<usize> { thread_local! { static ID: Cell<usize> = Cell::new(0); } ID.get().checked_add(1).inspect(|&new_id| ID.set(new_id)) }
mutableなRange(0..)をIteratorとして使う小技があるけど オーバーフローは意識したことないな fn new_id() -> Option<usize> { use std::cell::RefCell; use std::ops::RangeInclusive; thread_local! { static ID: RefCell<RangeInclusive<usize>> = RefCell::new(0..=usize::MAX); } ID.with_borrow_mut(|ids| ids.next()) }
>>105 Cellで済むところがRefCellになってしまってメリットがよくわからないです
合わせたつもりだったけど104の実装だと最初のidは1か
0から開始できる形でCellにこだわるなら↓みたいな実装もありそう fn new_id() -> Option<usize> { thread_local! { static ID:Cell<Option<usize>> = Cell::new(Some(1)); // ←0開始ならSome(0) } ID.replace(ID.get().map(|i| i.checked_add(1)).flatten()) }
>>104 をマルチスレッド対応するなら
まず初心者入門向け版としてはCellをMutexに変更で動く
fn new_id() -> Option<usize> {
static ID: Mutex<usize> = Mutex::new(0);
let mut id = ID.lock().unwrap();
id.checked_add(1).inspect(|&new_id| *id = new_id)
}
正しいようだが何を問題視してる? ちなみにRustではmatch(またはif let)で書いた時に 次のようなパターンになる場合に わかりやすく短くメソッドにして繋げることができる and_then(f) | Some(x) => f(x), | None => None, map(f) | Some(x) => Some(f(x)), | None => None, inspect(f) | Some(x) => { f(x); Some(x) } | None => None, or_else(f) | Some(x) => Some(x), | None => f(), unwrap_or_else(f) | Some(x) => x, | None => f(), ok_or_else(f) | Some(x) => Ok(x), | None => Err(f()), など
語彙の問題もあるのかもしれないけどasyncの問題もあって中の人たち含めみんな昔ほどコンビネータで書かなくなった
Optionを自然に真偽値ベースで英語で読むと判り易くなっている 例えばunwrap_or_elseは 真ならunwrapすなわちSome(x)→x orは前提が偽つまりNoneの場合がfの対象でNone→f() 似ているor_elseは Some(x)→Some(x)となる部分だけ違うとすぐわかる その逆は当然and_thenとなり andは前提が真の場合がfの対象でSome(x)→f(x)となる 通常の動詞1つの時は真つまりSome(x)の時が対象で mapは値を写像してSome(x)→Some(f(x)) inspectは値を変化させずに実行Some(x)→{ f(&x); Some(x) } filterも値は変化させずに実行して偽なら捨ててNone Some(x)→if f(&x) { Some(x) } else { None }
あほくさ。 そこらの医学でも物理でも法律でもいいが適当な論文が単語や言い回しだけ平易にすればバカでも読めるようになるか? 前提知識がないとどうせ意味なんかわからん。 プログラミングも同じ。 理屈が理解できるだけの能がなければ表現ばかり平易にしても無意味。 不必要に難解にする意味はないが、言い回しだけ過度に平易にする意味もない。
特定のプログラミング言語を使えることを物理医学レベルと思ってるのは思い上がり
>>120 どこをどう読んだらそんな風に読めるんだ?
言語は当然にそれで表現すべき何事かがある (書く人はそれを理解している) という話なんやが。
>>121 自分はバカだと自覚したほうがいいぞ
ソフトウェア開発するならな
>>122 それは大変によくわかる。
自分で書いたものすら意味わからんようになるのは普通のことだからな……。
だから意図を表現することが大事で、小さなロジックの断片にでも名前を付ける。
その状況を表すための名前 (専門用語) こそが大事。
訓練されていない人にとって平易であることとは違う。
>>116 現状追認主義なのに推奨されてる用量・用法は守らず動くだけのコードを披露したがるのは理解できないんだが
ママに褒めてもらいたい幼児の心理だよ わかりやすいだろ
>>117 「ごっちゃに書いて見通しの悪いコードにはせずに、
高階関数のメソッドチェーンにして、
各々のメソッドで個別に関数またはクロージャで処理を指定する。」
ここまでは共通認識でいいんだよね?
万が一これにも反対の人がいるならばまずは代案を明示的に出してほしい
以上の共通認識の上で
語彙の問題という話が出ているからメソッド名の付け方に問題があるということなのか?
それともメソッドが多すぎる(機能が多すぎる)またはメソッドの分別の仕方に問題があるということなのか?
まさか高階関数がわかりにくいという話ではないと思うが
なんでもメソッドチェーンで繋げればいいわけでもなければ
なんでも分割して書けばいいわけでもない
ケースバイケース
一番ダメなのは慣習や暗黙の了解を無視したコード
>>104 や
>>110 はその一番ダメなやつ
つかこんな基本的なことから説明させようとするなよ
>>127 んでお前ならどう書くんだ?
Rust使った新システムで慣習や暗黙の了解はまだない時に自分で考えてソース書くときはどうするんだ?
>>127 また自分勝手な慣習や思い込みの暗黙の了解かよ
vecs.iter().map(|x| x.iter()).flatten().filter(...) みたいなのは書いてて気持ち良いけど、全員が賛同するわけではないよな Rustの公式のドキュメントだって関数型スタイルの書き方と手続き型スタイルの書き方の両方を紹介してるわけだし そういう「高度な書き方」をバッサリ切り捨ててるGO言語が人気というのもそう
>>127 具体的に何を問題視してるのかわからん
Mutexを使わずに効率よく実装できるケースのようにみえるが
初心者入門向けと書かれてるからMutex利用もアリだろう
>>130 そのコード自体はともかく
そういうメソッド連鎖は標準ライブラリや有名クレートのソースにいくらでも出てくるぜ
まずはソース読んでみな
>>132 自分も好みとしては関数スタイルを使うよ
だけど
>>126 のような「それが正しい形であり、みんなそちらを使うべき」みたいな言説はあほらしい
有名どころのOSSのコントリビューターだって、利用者からの質問への回答やチュートリアルでは 「for文で一つずつ要素を Vec に push_back で詰める」コードを示すことも実際にある
Rust開発者は関数スタイルを好む人も多いと思うけど、それは好みの域を出ないと思う
まあ存在する以上はユースケースがあるってことだからな。
コードゴルファーのために存在してるわけじゃないからな
そろそろitertoolsを標準ライブラリ化する話はないのか?
個別に取り入れられてる まとめて標準化はない 棲み分け
>>127 そのマルチスレッド対応コードに
指摘の「慣習や暗黙の了解を無視したコード」とやらが見当たらないのだが
そもそも慣習や暗黙の了解とはどういう意味で使ってる?
>> マルチスレッド対応するなら
>> まず初心者入門向け版としてはCellをMutexに変更で動く
>>
>> fn new_id() -> Option<usize> {
>> static ID: Mutex<usize> = Mutex::new(0);
>>
>> let mut id = ID.lock().unwrap();
>> id.checked_add(1).inspect(|&new_id| *id = new_id)
>> }
こういう C のコードを Rust で描く場合どうやればいい?
VIDEO もちろん unsafe 利用 ok として
型のキャストは std::mem::transmute
assert_eq!((3.14_f32).to_bits(), 0b1000000010010001111010111000011_u32); assert_eq!(f32::from_bits(0b1000000010010001111010111000011_u32), 3.14_f32);
>>138 中級者向けにはこれでええんかね
fn new_id() -> Option<usize> {
static ID: AtomicUsize = AtomicUsize::new(0);
let mut old_id = ID.load(Relaxed);
while let Some(new_id) = old_id.checked_add(1) {
match ID.compare_exchange_weak(old_id, new_id, Relaxed, Relaxed) {
Ok(_) => return Some(new_id),
Err(updated_old_id) => old_id = updated_old_id,
}
}
None
}
Rustに興味出てきたからとりあえず、とほほさんのサイトに目を通してみたんだけど
…もしかしてあの方、非同期処理と並列処理をごっちゃに理解している?
https://www.tohoho-web.com/ex/rust.html#async-await >>143 lock freeはそう
今回のアルゴリズムはRelaxedでも大丈夫だがmemory orderingに注意を要する
>>144 executor (runtime) とそこでの使い方次第
single thread で並列(parallel)なく並行(concurrent)のみも可能であるし
それをmulti threadで並行並列も可能であるし
blockさせて並行なく専属並列も可能
WebAssemblyはRustが主流なイメージだけど実際どんなもんだろ
linuxカーネルがシェルスクリプトの付属品にならなかったのはシェルを変更できるから だがjsは、変更不可能にすればjsが永久に主流だというのを意図的にやっている
だからマルチスレッドで発生しうる競合はその2つだけじゃないから それだけで安全と言い切れるわけないだろ そもそも安全性ってお前が作るアプリで必要なの? Linuxカーネルや組み込みだったらわかるけどそんな高度なプログラム作ってんの? 飛行機のシステム作ってて命がかかってるとかならわかるが、その辺のアプリで安全性とかどうでもいいよね Rust馬鹿信者は開発生産性を軽視しすぎだ、開発生産性を犠牲に安全性に振ってるのがRustだがアプリの特性によって安全性なんぞどうでもいいことが多い 開発生産性が一番重要
難しさによる障壁はあるけど、慣れれば生産性自体は高い言語だと思う ライブラリ多いし、ちょっとしたツールを作る程度ならエラーハンドリングもそんなに頑張らなくて良いし (anyhow を使えば割と雑に書ける) 流石にPythonのような手軽さは無いけど、C++よりは遥かに書きやすいし、個人的にはC#やJavaよりも楽だと思うくらい これは言語仕様でなくツールの話だけど、プロジェクトを作ったり、ライブラリを追加したりするのが楽 学習コストが高いのはその通りで、誰かが書いたツールを他の人が保守しづらいみたいな問題はどうしようもないけど… (そういう用途ならGoが良さそう)
>>154 他人が書いたコードの保守しやすさはGoより上だと感じてるけどな
型含めてコード上に情報が豊富で作者の意図を取りやすいから
かなり巨大なOSSでも割と楽にプルリクとか出せる
>>155 「自分がRustに慣れてるなら」それは自分も同意
自分の意見は
・Rustは分かるようになるまでが大変
・理解できれば開発者にとって強力な言語
で、「Goの方が向く」というのはとっつきやすさを含めた話のつもりで書いた
他言語の経験者から見たら、たぶんRustは型やトレイトの意味を理解するのが難しいし、参照などのルールを理解しないとコンパイルすら通らないから、Goの方が触りやすいんじゃないかと思う
Arc, Rc, Cell, Mutex とかの型は分かる人にとってはmeaningfulだけど、初学者がすぐに分かるものではないと思う
>>156 単純にメンテする人員を確保しづらいという意味ならそれはそう
rustのいい所はresultやoption.その他色々な型について文脈が大体決まっていること。なので慣れると人が書いたコードでも読みやすい。c#やjavaとの比較であれば開発効率は大体同じか、勝っているぐらい。nullや例外がある言語はプログラムがどうしても汚くなる。 rustはaiにコード生成させた時の品質も割といい。コンパイルエラーでても対応方法が具体的なのでそのままメッセージをaiに渡すだけで直る。
AIが当たり前の時代においてはコードの記述量そのものは開発効率に直結するものではなくなる。どの言語でも似たような事は出来る。でも作られたコードが、正しいかどうかは別の問題。 AIはたまに嘘を付くので、それをコンパイラで厳密にチエックする必要がある。そういう意味では関数型言語へのシフトは進むし、rustはいい位置にいると思う。
>>159 関数型である部分ではなく
Rustが安全性にも役立つ史上最強の型システムを構築したことが決め手かな
特にトレイトそしてトレイト境界
さらに例えばSendやSyncといった概念的なトレイトなど
九連休に一回もコード書いてない陽キャはこのスレ書き込み禁止な
体力落ちないように散歩しまくってたら脚の裏に豆出来たよ
陰キャなのに今年のコード書いてなかった fn main() { println!("{}年", (0..10u64).map(|i| i.pow(3)).sum::<u64>()); println!("{}年", (0..10u64).sum::<u64>().pow(2)); } sum()の型アノテーション外せないの?
>>167 型アノテーションは必要。
オーバーフローしない十分に大きな型を選定しなきゃならないから。
浮動小数点ならオーバーフローはしないが必要な精度を推論しようがないことにかわりない。
0..10がu64なんだからsumの結果も当然u64だろうという気持ちにはなる
そこは指定必須 例えばu64の和をu128で求める型を以下のように増やせるから無指定を許すとコードが曖昧になる struct MySum(u128); impl std::iter::Sum<u64> for MySum { fn sum<I: Iterator<Item = u64>>(iter: I) -> Self { iter.fold(MySum(0), |sum, n| MySum(sum.0 + n as u128)) } } fn main() { // u64の和をu128で計算できる let x = [u64::MAX, u64::MAX].into_iter().sum::<MySum>().0; assert_eq!(x, u64::MAX as u128 * 2); // このコードはデバッグモード時にoverflowして悪手 let x = [u64::MAX, u64::MAX].into_iter().sum::<u64>(); assert_eq!(x, u64::MAX - 1); // ラップアラウンドさせたいならこうする use std::num::Wrapping; let x = [u64::MAX, u64::MAX].into_iter().map(|n| Wrapping(n)).sum::<Wrapping<u64>>().0; assert_eq!(x, u64::MAX - 1); } このように必ず型を指定して使い分けをする
Monoidを先に整備すればこんなことにはならずに済んだろうに
>>171 そういうのは本来sumの役割じゃなくないかという気持ち
オーバーフローとかは関係なくて型システムの制約と標準ライブラリの実装方法の問題だよ
sum()の戻り値の型をIterator::Itemに固定するとItemが参照型の場合に対応できないな
ジェネリクスで良いとは思うけど、デフォルトの型として元の型になってくれると便利な気はする 参照の場合とかは、数値型なら .copied() で値にできるし
>>177 copy可かつcopyでコスト増にならないのはプリミティブな数値型だけだよ
巨大な整数値やタプルや行列などもありうる
例えば std::simd::Simd のimpl Sumでも参照を扱ってるね
impl<'a, const N: usize> Sum<&'a Simd<u32, N>> for Simd<u32, N>
もうfoldでいい気がしてきた fn main() { use std::ops::Add; println!("{}年", (0..10u64).map(|i| i.pow(3)).fold(0, u64::add)); println!("{}年", (0..10u64).fold(0, u64::add).pow(2)); } 3乗の総和=総和の2乗の証明は今年の入試で狙われそうだな 帰納法使えば簡単だけどn(n+1)/2の導出からだとだるい
そのSimdのSum実装のこれを見てそこに落ち着いたのか iter.fold(Simd::splat(0 as $type), Add::add)
Rust排除のためのMozilla潰しが始まったか?
GoogleとLinux FoundationがChromiumの開発と維持を支援する基金「Supporters of Chromium-Based Browsers」を設立、MetaやMicrosoftなども参加 - GIGAZINE
https://gigazine.net/news/20250110-supporters-of-chromium-based-browsers/ Rust を導入する目的は、シンプルで(IPC を使わない)安全な(全般的に C++ よりも複雑でなく、サンドボックスでメモリの安全性に関するバグは発生しない)形で 2 の法則を満たすことにより、
Rust は、Mozilla がブラウザを書くために特別に開発したものなので、このテクノロジーが Chromium でようやく使われ始めるようになるのは、理にかなったことです。 システム ソフトウェア業界に莫大な貢献をしてくださっている Mozilla に感謝いたします。 Rust は、安全性とパフォーマンスの両方を言語に期待できることを見事に証明しています。
そもそもMozillaはRust開発者の大半をリストラしてしまったし すでに単なる1ユーザ企業に過ぎなくて、Rustの発展にはあんまり関係なくなってる どちらかというとMDNを維持できるかとかの方が重要そう
GoogleはChromeが独占禁止法違反にならないようにFirefox支援しててMozillaは生きててもらわなきゃならん デフォルトの検索エンジンに採用する見返りにGoogle社から受け取ってる金がMozillaの収益の90%を占めるから潰すのはその金を絞るだけでいい
>>187 おまえ日本語不自由なら無理に書き込まなくてもいいんだよ?
添削してあげる GoogleのChromeが独占禁止法違反にならないように対抗馬のFirefoxにある程度台頭してもらう必要がある そのためGoogleはMozillaを投資している 投資の一例としてMozillaはデフォルトの検索エンジンに採用する見返りにGoogleからMozillaの収益の90%を占める投資を受け取ってる 仮にGoogleがMozillaを潰すのならその投資を絞るだけでいい
訂正 誤 そのためGoogleはMozillaを投資している 正 そのためGoogleはMozillaに投資している
>>190 俺より頭が良さそう
尻拭いしてもらってすまんな
ところがMozillaに資金援助してるのが 独禁法違反ともめてるわけだ
ChromeもMozillaも各々Rust化へ向かってるなら 今後はここでもう揉めなくて済むな
Rust 1.84.0でprovenance関係が安定化されてるね
Rustで描かれてるMozillaがめっちゃ不安定なんすけど
>>199 Mozillaのメモリ管理や中核部分はC++で書かれている
>2016/07/20 まとめ:Firefox 48 には、Rust で書かれたコードが初めて含まれます。以降のバージョンにも Rust での実装が予定されている部分があります。 10年掛けてまだ置き換わってないってどういう事なの
現場を動かすほどの言語じゃなかったってこと いずれ忘れ去られていくだろうねw 必死で宣伝するやつはしばらく残るだろうけど
Rust化を進めようとしているのはChromeの方だよ
ソース
>>182 >>184 >>201 単純に考えてその時点で約20年積み上がってからね
firefoxシェアほとんど無くなって自立収入ではやっていけなくて 独占禁止法を逃れるためのGoogleからの資金で開発やってるから 基本部分は変えずに独自機能の強化の方に力を入れてるんじゃないかな
WindowsのOsStringってなんでUTF-16直接保持しないであんな面倒なことやってるんだろ
>>207 Rustは時代に応じて文字列をUTF-8で扱っていてString型には必ず正規なUTF-8が入ることが保証される
しかし外の世界は魑魅魍魎でUnicodeですらないものを扱えないといけない
ファイル内容やネット通信でUTF-8以外が定められてるならencoding_rsを使って明示的に変換しながら読み書きする
>>207 一方で問題となるのはファイルシステムのパス等だ
OS環境毎に異なるプログラムは書きたくないからコード上はString型つまりUTF-8で統一して扱いたい
パスがUTF-8自体もしくはUTF-8に1対1で対応するUTF-16等ならプログラム中はString型(=UTF-8)で扱えてうれしい
しかしパス内にはUTF-8に変換できないものも含まれている可能性があるためOsString型(=UTF-8+α)として区別して扱う
>>207 OsString型は以下の2つを満たす抽象的な型となっている
正規UTF-8のみを含むならばコスト無しでString型に変換できて逆にString型からは常にOsString型にコスト無しで変換できる
各OS環境で扱える全ての表現と1対1に対応できる(特に正規なUnicodeならばUTF-8に対応する)
この1対1が重要でありUnicodeでない場合も読み書きしての同一性が保証される
これらを満たせば内部の構造は自由でありユーザープログラムがその構造に依存することはなく構造を知る必要もない
>>207 Windows OSのUTF-16環境であってもユーザープログラムは環境の違いを気にせず統一して扱えるようにString(=UTF-8)とOsString(=UTF-8+α)で扱う
そのため正規なUTF-16はUTF-8に変換して内部で扱うことになる
しかし実際には任意の16bit列がパス等に現れることも可能なのでUTF-16以外の場合も1対1にOsStringに変換できなければならない
この任意の16bit列にはUTF-16のみの場合も含まれるため区別してWTF-16と呼ぶ
つまりWTF-16=UTF-16+αの関係になっている
あとはそれと1対1に対応するWTF-8=UTF-8+αを上手く定義してやれば前述の性質を満たす内部構造が完成する
以上おわり
> Windows OSのUTF-16環境であってもユーザープログラムは環境の違いを気にせず統一して扱えるようにString(=UTF-8)とOsString(=UTF-8+α)で扱う OsStringの内部エンコーディングがWTF-16だと統一的に扱えないと言いたいの?
String <-> OSString <-> System Native String 右の変換コストよりも左の変換コストを下げることを優先してる そのほうが標準ライブラリ内部で共通の実装や似通った実装を使いやすい
System Native Stringは直接取り扱わず、OsStringでラップして扱うのが原則なら ゼロコスト抽象化の観点から言えば右の変換コストをゼロにするべきでは? 左の変換は必ず行うとは限らないのだから
というか、Windows以外なら実際右の変換が実行時チェック無しのゼロコストになってて、左の変換時にチェックしてるんだから、その説明には合わないじゃないか どこにそんな説明が書いてあるんだ
>System Native Stringは直接取り扱わず、OsStringでラップして扱うのが原則なら 別にそんな原則ない OsStringで楽できないなら使わなくてもいいよ >ゼロコスト抽象化の観点から言えば右の変換コストをゼロにするべきでは? それは君がマルチプラットフォーム対応のライブラリを維持管理する立場で考えず Windows中心でしか物事を見てないからだよ >というか、Windows以外なら実際右の変換が実行時チェック無しのゼロコストになってて、左の変換時にチェックしてるんだから 間違って理解してるね >どこにそんな説明が書いてあるんだ 公式ドキュメント
? ちょっと調べたらバレるくだらない嘘つくんだったらもう相手してあげないよ
外部と内部でデータの表現形式が異なる場合 外部に従属するソフトウェアを作ってるのでなければ 可能な限り境界に近いところで変換を行うのは当然の選択
外部とUTF-8変換する微々たるコストが深刻になる用途があるならば標準ライブラリを使わずに独自に実装すればよいだけの話 標準ライブラリはAsRef<OsStr>やAsRef<Path>でそのままstrやStringが使えるように設計されている File::openなどでのパス指定の引数もこのAsRef<Path>がトレイト境界となっている as_で扱える設計が望ましい
>>221 後半ためにはOsStringがStringを含む拡張になっていなければならない
そうなっていれば型の読み替えだけでas_refできる
>>222 それは
>>213 が書いてるようにどうなってるかの話で
なぜそうなってるかの理由ではないよね
File::openはAsRef<Path>を受け取るけど
windowsならすぐにVec<u16>に変換されてる
仮にwindows向けOsStrの内部がu16ベースで
File::openがInto<Path>を受け取る実装だったとしても
処理内容は変わらない
>>223 それは違うな
str.as_ref()と参照を読み替えるだけでOsStrになることが重要
そのためOsStrとstrのPartialEqも用意されていてコストなく比較可能
UTF-8のみであればOsStrとstrは一致することが本質
>>224 どれも結果であって原因ではないね
>str.as_ref()と参照を読み替えるだけでOsStrになることが重要
なんで重要なの?
>そのためOsStrとstrのPartialEqも用意されていてコストなく比較可能
OsStrとstrをコストなく比較可能にするために
System Native StringをOsStrにするタイミングでコストがかかってる
コストをかけるタイミングだけの違い
OsStrとstrがコストなく比較可能でなければならない必然性は全くない
ファイル操作なんてI/O負荷の方が高いんだからファイルパスの変換コスト気にする必要あるか? 文字コードが違う環境はwindows以外にも色々あるだろうし。
直交する話を持ち出しても元の議論には一切影響しませんが
一般的な話として アスキー非互換かつサロゲートペア問題を抱えるUTF-16は欠陥品なので使用は好ましくない UTF-16や16bitで扱うシステムはユニコードが16bit時代に決めた古いシステムがほとんどで稀に後に無知者が導入したものがある程度 Rustで文字charは正しく32bitとなっており 文字列strはネット上やファイル内でも推奨されアスキー上位互換のUTF-8になっている さらにOsStrはそのUTF-8の上位互換となり集合的にはOsStr⊃str⊃アスキーとなっている それさえ満たせば細かい内部実装は各OS毎に異なってよい 欠陥品のUTF-16は何も満たせずそこでも排除で正しい
OsStringの用途はファイルパスに限られたものではないけど主たる用途で性能が問題にならないというのは今の実装方法が選ばれた理由の一部ではある
UTF16はメモリとパフォーマンスのバランスが良い オンメモリの内部形式としては悪くないチョイス
別に理由が無いなら無いと言えばいいのに、変にこじつけようとするから
スレを荒し続けているUTF16信者は何がしたいの? 本気でUTF16がいいと信じているならそういうcrateを作って布教すればいい そんな需要はないと思うが
>>225 それは
>>219 が述べるように「変換は境界で」という基本思想による。
このやり方が複雑さを避ける良い方法だというのは歴史の積み重ねで皆が実感してきたことなので今さらどうこう言っても「その話はもう終わった。蒸し返すな」という気持ちなんだよ。
じゃあせめて「その話」がどのissueでされたかでも貼ってくれないかな
わかった 少なくともこうして容易に使えることが最低必要条件 fn OsStr::to_str(&self) -> Option<&str> したがってOsStrはstrを含む拡張集合 それ以外に制約はなく各OS毎に内部実装は自由
impl AsRef<OsStr> for str
issueで内部が16ビットではそれが機能しないと
>>232 特定のプラットフォームに依存するコードはなるべく減らしたいという動機は理解できるんだよね?
可能な限り境界に近いところで外部表現と内部表現の変換を行うことがプラットフォーム依存のコードを減らすことに寄与するというのもわかるよね?
あとは外部の表現形式を内部でも維持したとしてもデメリットを上回る十分なメリットがあるかどうか
OsString/OsStrの主たる用途ではそれだけのメリットはないという判断
メリットがある用途ならOsString/OsStr以外を使いましょうということ
str <-> OsStrの話は差異をうまく隠蔽しにくくシグニチャに影響しうるというのがあるけど仮に影響しなくても境界で変換するのが望ましいという判断は変わらなかったはず
>>247 ありがとう、RFCのほう探せばよかったのか
> ## Wide string representation
> Downsides:
> * These conversions have inconsistent performance characteristics between platforms. (Need to allocate on Windows, but not on Unix.)
やっと納得できる理由が出てきた、これはたしかにな…いやでもなあ、直接OsString/OsStrを触るAPIがもっと充実していれば別にString/strとの変換をそこまで気にする必要もないのでは?
一気にString/str相当のAPIを実装するのも手間だし、OsString/OsStrで何かやりたかったらとりあえずString/strと変換してなんとかしてくれ、だからここではプラットフォームごとの差を付けたくない、って方針だったのかね?
とはいえ、考えられる発展としていろいろな文字列型を一般化する抽象化を作れるはずとかちゃんと書いてあるし、まあまあ納得できる経緯説明ではある
ありがとうね
> // and ultimately other functionality typically found on vectors,
> // but CRUCIALLY NOT as_bytes
…とか書いてるけど、今は普通にas_encoded_bytesとして実装しちゃってるし、結局なんだかよく分からんなあ
>>248 >> * These conversions have inconsistent performance characteristics between platforms
こう書かれてるけどパフォーマンスという点では特にDownsideじゃないと思うんだけどね
今の実装でも発生してるし違う環境用のOsStringを1つのプログラムが実行時に混ぜて扱うわけでもないし
問題なのは内部コードにアロケーションタイミングの違いみたいなのが侵食して分岐が増えること
わかりやすい例としてはOsStr::new(“foo”)が&OsStrを返せなくてCow<OsString, OsStr>になるとか
そうだね だから現状の仕様で正しくて 10年間も問題視されていない 許容できない用途が仮にあるならWindows専用のクレートを作ればいい
> # Alternatives > * A split_at(&self, pos: usize) -> (&OsStr, &OsStr) style method. This is ostensibly simpler than a slicing API. But: > ** The OMG-WTF-8 encoding does not support this. It requires some splits to produce overlapping slices, so that left.len() + right.len() > orig.len(). The encoded bytes on one side of pos might form a valid OMG-WTF-8 string while those on the other side do not. > *** RFC #2295 that proposes this encoding was merged five years ago (but has not been implemented). 何その絵に描いた餅を喉に詰まらせて死ぬみたいな話……
ほとんどのシステムはUTF-8以外のファイル名があったら無視かエラーでいいからどうでもええわ
LinuxカーネルのメンテナがRustコードを混ぜることを「癌」と呼び、開発者間の対立が激化中 - TechFeed
https://techfeed.io/entries/67a52d4677bdbc0f2990eed9 争え……もっと争え……
そりゃドライバーはカーネルのインターフェイスに従って動作すべきだから、ラッパーなりで隠蔽すべきなんじゃないんかね。 個別のドライバーのためにカーネル側をカスタマイズするのはインターフェイスを侵食する越権行為だから、そんなのドライバーのラッパー側でやれ、と言いたくなるのはわかる。
>>257 それは君の理解が間違っている
今回はRust製の各デバイスドライバが独自のCバインディングを持つ不便な状況を改善するためのパッチだ
つまりカーネルのC側に手を入れるパッチではなくC側は同じままで変更は一切ない
今回の件は該当部分dma_alloc_coherent()のC⇔Rustの抽象ラッパーのコードを含めるパッチだけだ
それさえメインテナーに拒否されたため大問題になっている
デバドラはRustで書くのが普通になってきているから そういう共通ラッパーという形のRustインターフェイスが色々と欲しいのよね でもそれはいずれカーネル自体のRust化へ繋がる道になるから強く反対してるのよ
普通に考えたら異種の言語が混ざるとデバッグと開発の障害でしかないからどこかで境目は必要
>>258 メンテナーがRust用コードのメンテナンスを拒否したということじゃないの?
Rust for Linuxでサポートするような話じゃないんかね。
>>260 異種の言語を混ぜる話なんか誰もしていない
今回の事件のパッチも異種の言語を混ぜることなくCのAPIはそのままで
その上にRustの層を作る話
In response, Krummrich explained the Rust for Linux effort is creating Rust code that abstracts the C APIs for all Rust drivers and is maintained by Rust devs. In other words, the C side of the kernel stays the same, and Rust drivers use abstractions to that C code, and that these abstractions are maintained by a team centrally in rust/kernel, all of which is arguably better than drivers having their own individual C bindings.
最終的にRust側のメンテナが切れてSNSで晒したりしたのは良くなかったけど 技術的にはC側に迷惑かからないように十分配慮して、出てきた懸念も全て潰したにも関わらず 「とにかくRustに関わりたくないから却下」だったからまぁ切れるのも分かる
>>263 そのコードはcで使えるの?
使えるならともかく、Rust専用ならメンテナーが「そんなののメンテナンスで負担増えるのは嫌だからRustドライバー側でやってくれ」というのもわかる。
Rust for Linuxはこういうのの受け皿にならんのかしらん?
>>264 受け皿も何もそもそもRust for Linuxでやってる話だし
完全にRustドライバー側でやるからCには影響しないって言ってるわけ
具体的にメンテナンスの負担が増える理由を挙げてくれれば対応策も考えられるけど
「とにかくお前らを邪魔するためなら何でもする」って言ってるからどうしようもない
>>265 メンテナが「Rustは俺のサポート範囲に出てこないでドライバ内で閉じてやってくれ」と言うんだから、当面はrust fir linux でドライバーのテンプレートを作るなりCバインディングサポートライブラリを作るなりすればいいんじゃないんかね。
「Rust製の各デバイスドライバが独自のCバインディングを持つ不便な状況」というのもrust fir linuxでフレームワーク作ってサポートすれば解決するし。
互いにブラックボックス内でなにが起ってるのかわからないとすると困るけどね コレコレこういうコードを書いたらこういう結果が出るはずなのに出ないとコード提示されても 相手が理解できなければこじれるだけ
>>266 そこで言う当面はってのは3-4年前の状況かな
今はもう準備も整って、Mac用のAsahiLinuxとかAndroidとかフォークしてる勢には普通に入ってる段階
だからそろそろ本体にって話になってるわけだけど、拒絶されるなら彼らはフォークに戻っていくだけだとは思う
内部の問題をSNSつかって文句言うなアホ お前が問題じゃ
ここや他のスレでRustに意味のわからん難癖つける人が いるのは5ちゃん民度のせいではないのがわかった
C++に似ている部分はC++と同じ程度に批判される それとハイブリッド的な部分 100%ガソリンで動くか100%電気で動くかどっちかにしろという
>>268 該当コード用のメンテナがRustを使いこなすようになるか、専用のメンテナが別に現れるか、現在のメンテナが引退してRust推進のメンテナに代わるまでじゃない?
これはメンテナの複雑性管理&管理ポリシーの問題だから、普及具合とかはあんまり関係ない。
色んなものがRust製になっていく中 最後まで残りそうなのが巨大でモノリシックなカーネルとブラウザになりそうだな
日本の古文漢文は残らないかもしれないが西洋では全部保存していて選択肢が増えるだけ だから、向こうが世界の中心みたいな空気になる
Linux カーネルは保守的な方針だろ。 数年前まで C89 が前提だったんだぞ。 この速度感で考えるなら Rust 導入なんてまだまだ時期尚早じゃね?
Firefoxのレンダリングエンジンは大分前からRust製(Servo)でしょ
>>278 Servoにそんな完成度はない
実験レベル
Mozillaお金なさすぎて色々と切り捨てて RustもRust Foundationへ移管されたもんな 結果的にRustにとっては中核が安定してラッキーになったけどさ > 2020年にMozillaがすべてのServo開発者を解雇した後、プロジェクトのガバナンスはLinux Foundation Europeに移管された。 > 開発作業は公式には同じGitHubリポジトリで続けられており、プロジェクト自体は完全にボランティア主導です。
C/C++その他の知識を蒸留してないわけがないから コストもコスパもないんだよ
Pointers (this includes values of reference type) in Rust have two components. - The pointer's "address" says where in memory the pointer is currently pointing. - The pointer's "provenance" says where and when the pointer is allowed to access memory. We have to know not only the address the pointer points to, but also track which other pointer(s) it is "derived from". Provenance is useful because it allows powerful optimizations. Provenance can affect whether a program has undefined behavior.
lud20250219202612このスレへの固定リンク: http://5chb.net/r/tech/1733146370/ ヒント: 5chスレのurlに http ://xxxx.5chb .net/xxxx のようにb を入れるだけでここでスレ保存、閲覧できます。 TOPへ TOPへ
全掲示板一覧 この掲示板へ 人気スレ |
Youtube 動画
>50
>100
>200
>300
>500
>1000枚
新着画像 ↓「Rust part27 YouTube動画>1本 」 を見た人も見ています:・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・なんUSTR部 ・SATORU ・citrus ・なんG RUST部 ・なんJ RUST部 ・STERUSS 2 ・なんU RUST部 ・RYUTist解散 ・SOUL TRAIN ・Naru Sato ・TRAP MUSIC ・SUPER GT+ ・DONGURTES ・SUPER GT+ ・catch surf ・Suzu Part1 ・test sure ・Crossout ・SUPER GT+ ・Rust part9 ・Rust vs Go ・SUPER GT+ ・SUPER GT+ ・SUPER GT+ ・The Surge ・Surgeon pt2 ・SUPER GT+ ・DISTURBED ・Soul Captor ・なんUSTR部 ★2 ・Fkindustry ・azusa part4 ・SUPER GT+ ・Rust part8 ・SUPER GT+ ・UberEats仙台 ・SUPER GT+ ・Rust Part5 ・Rust part16 ・Rust part20 ・Rust最強(仮) ・男Uber Eats ・PUSHIM Part1 ・tjrssukilou ・初心者Vtuber ・Botulus Rex ・Sproutsスレ ・なんUSTR部 ★2
18:21:56 up 63 days, 19:20, 0 users, load average: 9.65, 9.88, 9.94
in 0.097811937332153 sec
@0.097811937332153@0b7 on 062007