◎正当な理由による書き込みの削除について: 生島英之 とみられる方へ:Rust part27 YouTube動画>1本 ->画像>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.
生メモリいじくるのが好きな人たちがいきなりrustやれって言われたらきつい気持ちはわかる どうせメンテーなんてみんなジジイなんだし
Linusの今回の発言は明瞭で ・Cだけ触りたい人はそのままRustを覚えなくてOK ・その代わりRustについて口を挟む権利はない ・CのAPIをその利用者は自由に使えてメンテナといえども用途用法に口を挟む権利はない したがって今回もめていた「CのAPIの上にRustのAPIを設ける件」について Cだけ触りたいメンテナは口を挟む権利はなくパッチを拒否する権利もない、ということ 大方の人々が考えていた通りに決着
かつてカーネルを正しく修正した結果として (保証してない挙動に依存した) 間違ったアプリケーションのいくつかがまともに動かなくなったことがある。 そのときに Linux の理念としては技術的合理性でユーザー体験を損なってはならないということで間違っているアプリケーションに合わせて互換性が維持された。 ユーザは一方的な利用者に過ぎずカーネルに口出ししないなんてことはない。 絶対に、絶対に、絶対に、カーネルに口出しするよ。 まあそれが良いか悪いかは知らんけどな。
>>291 そういう具体性を欠いた屁理屈言って拒否するのは
やめろと怒られてるのだね
>>290 そういうデマを言うやつがいるとコミュニティー全体が嫌われるから止めるべき。
Linusが言っているのはせいぜい「Rustコードのメンテナじゃないだろ」ぐらいの話で、Linuxメンテナ失格とは全く言っていない。むしろメンテナが自分のメンテナンス範囲をCコードだけにするのを肯定している。
今回の件も、C APIユーザーとしてのRustコードがCコードとは独立した形で別のメンテナにメンテナンスされるんじゃないんかね。
着実にRust APIを増やしていこう 脱libc
Rustはリファクタリングでの安定度も他より極めて高くて開発効率が良いので まずは雑に書いて後から可読性を上げたり拡張性を上げたり実行効率性を上げたり普通に行われているね
>>296 クレート境界をダックタイピング化した言語が欲しいわ。
>>291 その動作は弊社製品の仕様です
(今後も動作は維持されます)
その動作は弊社製品の問題点です
(今後動作は変更されます)
>>298 ダックタイピングは各異なる型を統一的に安全に呼び出せる保証が人任せだから使うべきでない
トレイト境界を指定すれば安全が保証されるがそれはトレイトすなわち他言語で言うところのインターフェースに近い存在を仮定していてダックタイピングとは言い難い
>>301 >298のダックタイピングは静的ダックタイピングで構造的部分型のことね。
型の機能的な共通部分を部分型として統一的に扱うから、普通の型と同程度には安全かと。
>>298 Go だと型があるインターフェイスを満たす (満たすつもり) かどうかは明示的な宣言がない。
インターフェイスで定義されたのと同じメソッドを持っていればそのインターフェイスを実装したものと見做される。
>>302 まずその共通部分が存在する保証がない
次に共通部分があったとしてもその部分への任意のアクセスメソッドが完全に同一である保証がない
さらにダックタイピングで用意されるメソッドがその共通部分のみにアクセスされる保証がない
共通部分型方式には問題が山積み
一方でトレイト境界を用いると
共通部分を持たなくても安全に共通メソッドを増やすことができる
言語によるとしか言えない その言語にある道具なら、それが便利なら使って問題ないと思う C++だと標準ライブラリでもダックタイピングをごく普通に使うけど、それに文句を言う人もいないでしょ
C++のような古くてダサい言語は比較する意味ないだろ ダサくて自己責任となるダッチタイピングはお似合いだが
Rust書きやすいって言ってるのは大体c++から移った人間でそういう人がここに集ってる GC付きの言語から来たらそこまでは思わない
>>304 静的ダックタイピングとか構造的部分型はご存知で?
コンパイル時にメソッドとかプロパティとかの部分集合で互換性を判定しているので、通常の型と同じレベルで合致するよ。
>>310 >>304 を理解できるなんて君は天才だねw
A:「〇〇な言語があったらいいのに」 B:「言語によるとしか言えない」 A:「・・・」
Structural Typingでバイナリ境界を超えて新しいメソッドを追加できるようにしてしまうと衝突時のデメリットがメリットを上回る Rustにcoherenceがあるのと同じ
>>308 GCの有無は関係ない
異なる型に対するコードの共通化つまりジェネリクスの話
例えばクラスを使えば同じ基底を継承する派生同士は異なる型でも共通のメソッドやプロパティを使える
しかし同じクラス継承の関係しか扱えないのは制約がキツく各機能毎に継承で多重クラス継承など問題が多い
一方でダッチタイピングや構造的サブタイピングは無関係な型同士でも同じメソッドやプロパティがあるだけで暗黙に使える
しかし互換性がなく偶然同じメソッドやプロパティを持つ同士の利用をエラーにできない問題や暗黙であるため複雑化してくると分かりにくくなるなど問題が多い
そこで機能毎にインターフェース宣言と各型でのインターフェース利用宣言することで諸問題を解決し安全で保守しやすいコードにすることができる
そしてインターフェース名(機能名)が付くことで複数の機能の列挙や関係も宣言できるようになる
Rustではトレイトと称する
llmの3B当たりが吐き出す文章みたいで何を言ってるのか意味不明だな
丸一日調べてこれとか泣けてくるな ついでにRustのトレイト問題も調べとけよ
>>313 最初の一文は違うだろ
A. 「(Rustにない、他の言語では使われてる機能) は問題だらけ」
っていう主張に対して反論されてるだけ
ダックタイピングは動的か静的かに関わらずデメリットが多すぎて使うべきではないよ 唯一のメリットはinterface宣言が不要だけどこれが害悪を招いちゃう interface名がないから可読性が悪く保守性も低いのはもちろん利用方法に制限も
静的なダックタイピングにはinterface宣言もinterface名もあるやろ
>>323 名前をつけて宣言したらそれはinterfaceそのものだよ
名前も宣言もなしで共通のメソッド名など構造が同じなら動作することがダックタイピングだよ
構造に頼るよりも、ジェネリック関数でトレイト境界で制約かけた方がRustっぽい気がする。 なんとなく。
>>324 上に出てきてるように構造的部分型(Strructural Subtyping)を含めた話
まあ俺もStrructural Subtypingを静的ダックタイピングと呼ぶのは
誤解を招きやすいからあまり賛同しないがそこは問題じゃないでしょ
>>327 ジェネリックの型パラメータをトレイトで制約するということと
その制約を満たしてるかどうかを型の構造に頼ってチェックするのは両立する話
共通する構造&機能がある時に ・interface名(Rustではtrait名)を付けて宣言するか ・名付けずにダックタイピングするか の違いが最も大きい 後者は様々な点で劣る 両者の中間的な位置付けにいるのがGo Goでは各型に対するinterface実装宣言を省略できてしまうため 省略すると可読性や保守性で劣ることになる
その「保守性が劣る」というGoは世間的には保守しやすい言語と言われてるんだが 型で守るという意味ではなく、多くの人に分かりやすい簡易な構文だからという理由でだけど
各型に対するinterface実装宣言を省略すると可読性や保守性で劣る その事実以外の話には言及していない
その可読性や保守性の劣化というのは現実にどの程度問題と言われてるの? 「自分は嫌い」というお気持ちじゃなくて? あるいは「Rustが採用してないから正しい」とか?
一般的に必要な情報は暗黙ではなく明記されている方が保守性も高いんだよ そして多くの人に分かりやすい 省略できるようにしたことはGoの仕様の失策だね
Goの場合は「省略できる」というよりも「書かない」というのが正しい 選択できるものではなく、常に書かないものだから 正直自分も好きではないし、だいぶクセのある言語だけど、世間的には受け入れられてる 世の中の人は案外そこまで型にこだわりはなくて、それよりも分かりやすさの方が好まれたりする それは単に「考えが違う」というだけで、劣るとか優れてるとかいうものではない (それなら何でGoは人気なの?ってなるし)
あとRust開発者はC++から来た人が多いと思うけど、C++のテンプレートは思いきり静的ダックタイプでしょ あれで実際「可読性ガー」ってなるより、便利だと思う場面もあるよね?
>>334 明記されていたほうが分かりやすいというのは正しい。
その一方で、明記しなくても分かるような設計にしろ (分かり難くなるなら設計が誤っている) という哲学が Go の根底にある。
structural vs nominalならが安全性はnominalのほうが高いが 保守性や可読性はどちらか一方が常に優れてるわけではないな Rustはよりメタルに近いOSやライブラリでの利用を重視してるから 安全性の面からより保守的な選択をしてる coherenceとかもアプリケーション開発者観点だと不必要に厳しい
Goでは省略しちゃうことが多くて、 ある型についてどんなinterface群を満たしているのか、を把握するために、 対象となりそうな全てのinterface群の各々のメソッド群と見比べて、 そのメソッド群すべてを実装していることを確認することで、 ようやくそのinterfaceを満たしていることを把握できる。 たった1行を省略できる利便性(?)のために、大きく可読性が落ちているのは否めない。
gopls implementationとかで確認すればいいよ
>>330 静的ダックタイピングは明示的インターフェイスでも成り立つよ。>336で言うならテンプレートとコンセプトみたいにテンプレート引数の要件を明示するやり方。
>330の言い方なら、
共通する構造&機能がある時に
・共通することを型としてあらかじめ宣言するか
・共通部分を使う時に判別するか
の違いですな。
後者は共通する構造&機能の決定を実際に使用する時まで遅らせることができるので、型の設計時点で決めなくてはならない前者よりも設計の自由度が増す。
Adapterパターンのサポートが充実していれば問題を緩和できるけど、Rustて充実してたっけ?
Rustは各型で共通事項をあらかじめ宣言する必要がなく 共通する構造&機能の決定を実際に使用する時まで遅らせて それらが決まってから後から実装すればよいため 設計の自由度が高いね
他人の書いたコードをインタフェースで抽象化したいときにGoのinterfaceは便利だけど 全て自分で管理する場合は明示的に宣伝した方がいいから選べるようにしてほしい Javaの普通のinterfaceに加えてGoのinterface同時に使える言語が欲しい
>>345 interfaceに関して欲しい機能はRustのトレイト境界の機能だろ
Javaには類似の境界型パラメータがあるが単相化しないため役に立たない
>>343 Rustで共通事項をあらかじめ宣言しないで、共通する構造&機能を統一的に使うのってどうすればいいの?
Rustの型システムを考えると、(既存のコードを変更することなく) 共通する構造&機能を新たに宣言して統一的に扱える、ということだよね?
リファクタリングをするのに既存のコードを変えないとか矛盾していて意味がわからん 後から共通メソッドをトレイト化すればいいだけだろ それで困る人はいない
>>350 例えば標準ライブラリの型との共通部分を統一的に扱いたい場合、標準コードをリファクタリングして新しい共通Traitを切り出すのかしらん?
Rustでコーディングしたことないお客さんが来てるのか? 標準ライブラリのコード自体を書き換えなんてせずとも普通に行われていることだぞ
>>349 >>343 が言ってるのはstructの定義時にそのstructがどのtraitを実装するかを(あらかじめ)宣言する必要はなく後から必要になった時にtraitの宣言及び実装をすればいいというだけの話
わざとずらしたことを書いてるから噛み合ってないんだよね
既に存在する共通する構造&機能をポリモーフィックに扱いたい時にGoなら必要なのはインターフェース宣言だけ 既存のインターフェースに合致するものなら新しく宣言する必要もなくそのまま扱える 一方Rustの場合は新しいインターフェースを宣言して既存の構造体に対する新しいインターフェース用の実装をそれぞれ追加で書かない限りは使えない それで済めばまだいい方で既存のインターフェースに適合させなければいけない場合は既存の構造体をラップする新しい構造体とその実装を逐一全部書いた上にインターフェースに対する実装も別途追加で書かないダメ 特に後者の手間は雪だるま式に膨れ上がるからライブラリのように他人に使わせるコードを書く場合は型の設計時点というより外部APIの設計時点で何を共通の構造&機能として使えるようにするか決めておく必要がある
> 既存のインターフェースに合致するものなら新しく宣言する必要もなくそのまま扱える 無茶苦茶だな そんな意図しない全ての型に自動適用される危険な言語は使いたくないわ Rustは明示的にimplしたものだけに適用されるから安全で使い勝手が良い
> 一方Rustの場合は新しいインターフェースを宣言して既存の構造体に対する新しいインターフェース用の実装をそれぞれ追加で書かない限りは使えない そんなことはない 既にimpl Tにあるのだからimpl Trait for Tへ移動させるだけだぞ > それで済めばまだいい方で既存のインターフェースに適合させなければいけない場合は既存の構造体をラップする新しい構造体とその実装を逐一全部書いた上にインターフェースに対する実装も別途追加で書かないダメ そんなことはない 既存の構造体にそのままtraitメソッドを増やせる
Rustでコーディングしたことないお客さんがこのRustスレでRust叩きとは完全に荒らしだ
外部クレートで定義されたトレイトを別の外部クレートの型に対して実装するときはラップが必要じゃない? 要素1つのタプル構造体 (いわゆる new type) で済むような話だけど インターフェースといってるあたり微妙にズレてる感はあるけど、「ラップする必要がある」という点自体は間違ってない
>>358 そんな話は誰もしていないよ
今話されているのはこれ
>既に存在する共通する構造&機能を
>新しいインターフェース宣言
複数の型に共通事項が出てきたから
新たなトレイトを作って宣言する話が行われてる
ラップは不要
自分の管轄外の型に対して、自分の管轄外のトレイトを実装することだけは、安全のため禁止されているので、自分の型にするためのラップが必要 そんな特殊な例外的ケースを除けばラップはもちろん不要
最初からクレート境界を前提とした文脈だろ
>>298 文脈読めよ
インターフェイス vs. ダックタイピング ダックタイピングはインターフェイス名がないため可読性が著しく低い インターフェイス名を使った制約も指定できない 必ずインターフェイス機能を使うべし
ダックタイピングは、意味が異なっていても、見かけの構造さえ同じなら、同一視してしまう問題もある つまりうっかり間違えて用いても、エラーを検出できないため、安全性で劣る。 その見かけの構造さえも、複数の構造を含む場合など、 この型はどのダックタイピングで用いられているのか、読み手が認識するのに時間がかかってしまう。 これらの問題は、各型において、どのダックタイピングに用いられているのかの宣言がないことに起因している。 一方で、interfaceは「各型でどのinterfaceを用いているのか」の宣言があるため、どちらの問題も生じない。
>>333 実行前(コンパイル時など)に問題が表面化することと
実行後に問題が表面化することの違いは果てしなく大きい
>>342 だからRustは清書用って言われるんだよ
>>351-352 type alias でほぼ何でもありな状態に出来るけど
他人のcrateとさらに他人のcrateを混ぜてると詰む
ああ 353 は引用なのか? 354 と 353 が同一人物ならきもいが 354 の言ってることが実情
>>359-360 struct に限ってはそうだね
>>342 Rustでは最初から共通部分があることを意識する必要がなく
そのような場合でも設計の自由度が高い
共通部分が生じたことに後から気付いた時点でそのためのトレイトを後から宣言すればよい
>>354 Rustならばラップは必要なく、トレイト宣言をしてトレイト側へメソッドを移動するだけで簡単に済む
impl Foo {
fn method(&self, ...
}
impl Bar {
fn method(&self, ...
}
と複数の型に共通メソッドがあり、それをトレイトで共通に扱えるようにしたければ
// トレイト宣言
trait TraitName {
fn method(&self, ...
}
// トレイト実装
impl TraitName for Foo {
fn method(&self, ...
}
impl TraitName for Bar {
fn method(&self, ...
}
つまり「impl Foo」から
「impl TraitName for Foo」へ移すだけで済む
今回の例なら差分タイプ量は「TraitName for」のみ
伸びてると思ったら複オジの類友が増えただけだったorz
>>376 structに限らず全ての型に対してトレイト実装によりメソッドを増やせるよ
&str(実質&[u8]でもVec<u8>でも)の末尾に ゴミで良いから毎回必ず'\0'付ける仕様にしといて欲しかった
>>381 '\0'に限らず任意の値を終端として型を定義できるZigの勝利だね
やっぱ崩れたかw 346みたいな偉そうな奴がいるとなw
>>381 必要な時だけ付けりゃいいじゃん
不要なものを常時付けとけとか頭おかしい
異なる方式を混ぜ合わせると両方を協調するのにミスが入りやすい。 ゼロ終端方式とファットポインタ方式に常に矛盾が生じないように維持するくらいなら必要なときに変換するほうがマシ。
>>375 >つまり「impl Foo」から
>「impl TraitName for Foo」へ移すだけで済む
>今回の例なら差分タイプ量は「TraitName for」のみ
フィボナッチみたいなトイコードしか書いたことがないと
こんな意味のない破壊的な変更を無自覚に書いてしまうんだな
>>381 "abc"の部分文字列"ab"を参照する時に元の文字列が"ab\0"になるけどいい?
>>381 &strはStringや(別の)strの任意の部分文字列を参照する型
もし末尾に'\0'を付加すると次の文字を'\0'で上書きするため原理的に不可能
Rustで'\0'終端文字列はCStr/CStringを使う
リテラルならc"ABCDE"
ちなみにC/C++で部分文字列を扱うと
同じ問題が起きるため別領域へコピーして末尾'\0'を付加する
さらに途中に'\0'を置くと千切れる問題や
長さを知るために'\0'まで要走査の問題があるので
Rustのstr/Stringでは'\0'終端文字列としていない
>>387 新たなトレイトを作ってメソッドを移しても破壊的な変更にならない
もちろん移すだけでは意味はないが
使う側でそのトレイト境界を用いてコードの共通化が可能となるため普通に行なわれる
>>391 昔も今もC + +のs t r i n g関数s u b s t r (開始位置, サイズ)は別の領域を確保してコピーだよ
\0終端するためにコピーは避けられないね
ちなみにライブラリ実装依存だろうけど
毎回ヒープ領域確保はコストが大きすぎるため
結果が15文字までならば静的に各16バイトの領域を事前に持っていてそこを使って頑張っていたりはする
でもそこへのコピーは避けられないね
>>390 うわぇー
なんでそんな嘘を吐くの?
もしかして破壊的変更の意味を知らない?
>>391 C++ の中だけでやるなら今は range を中心にライブラリが編成されてるから文字列の一部を取り出すのにコピーは必要ないしゼロ終端も不要だが、ここでは (古いライブラリなり API なりの都合で) ゼロ終端が必要になったときはという前提の話をしてるんだぞ。
外の世界は言語の都合に合わせて勝手に変わってくれたりはしない。
モダンな C++ を使っていても外と繋がる境界では外の都合に合わせなきゃしょうがないんだ。
>>394 Rustの中だけでやるなら文字列の一部を取り出すのにコピーは必要ないしゼロ終端も不要だが、ここでは (古いライブラリなり API なりの都合で) ゼロ終端が必要になったときはという前提の話をしてるんだぞ。
外の世界は言語の都合に合わせて勝手に変わってくれたりはしない。
モダンなRustを使っていても外と繋がる境界では外の都合に合わせなきゃしょうがないんだ。
君の言う前提に沿えば
>>389 の比較は無意味
>>395 「いつの時代の C++ だよ」に対していつの時代でもそうだよと言ってるだけ。
>>389 には興味ない。
>>395 あらためて
>>389 を見たら「ゼロ終端にするにはコピーが必要なのは同じだ (型の整理の仕方は違っても)」というのが趣旨だから結論が同じなのは意図どおりだろ。
>>389 CString::new(string)で0終端してくれて
c"ABCDE"は最初から0終端されてて便利だね
// 固定文字列は c"..." リテラルで作成
let c1 = c"ABCDE"; // &CStr型
// 文字列を組み立てる場合はStringで作成しておいて
let s = ('A'..='E').collect::<String>();
// そのStringを消費して0終端してくれる (途中に0があるとError)
let c2 = CString::new(s).unwrap();
// 左右どちらも &CStr型の c"ABCDE" で一致
assert_eq!(c1, &*c2);
このスレいつからワッチョイとかIDとか無くなった?
ワッチョイとかIDがあると自演するのに不便だからいらない
まともに他人の意見を尊重できる人たちが集まり議論が行われればそこが本スレになるだろうが、期待するだけ無駄じゃろ
>>398 自分で'\0'プッシュすればええやんと以前は思っていたけど
ミスがないことを型システムに保証してもらえる安心感
自分でNULL終端しようとする老害は 安全を保証する型システムと相性悪い
[c_char]が[u8]だと思ってたら[i8]だったでごじゃる
c_charは処理系依存っぽいからu8かi8に決め打ちするならc_ucharかc_scharにキャストした方がいい ターゲット変更した時にコンパイラに文句言われる可能性がある
\0終端じゃないと困るってcやc++から来た人だろ… 老害っているんだな
>>409 OS の要求ならしょうがないだろ……
適当なラッパー作るにしてもそのラッパーの中ではゼロ終端にしないわけにはいかん。
>>398 あとはCString/CStrからの変換だな
&[u8]として扱えるのは当然として
// CStringを消費して Stringとして扱う (非UTF8だとError)
let c = CString::new([b'A', b'B', b'C', b'D', b'E']).unwrap();
assert_eq!(c.into_string().unwrap(), String::from("ABCDE"));
// &Cstrを &strとして扱う (非UTF8だとError)
assert_eq!(c"ABCDE".to_str().unwrap(), "ABCDE");
// &Cstrを Cow<str> にする
// UTF8なら &strとして扱い Cow::Borrowed(&str)型
let cow = c"ABCDE".to_string_lossy();
assert_eq!(cow, Cow::<str>::Borrowed("ABCDE"));
// 非UTF8部分があると U+FFFD置換Stringにして Cow::Owned(String)型
let cow = c"AB\xccDE".to_string_lossy();
assert_eq!(cow, Cow::<str>::Owned(String::from("AB\u{FFFD}DE")));
いずれも'\0'の存在は気にしなくていい
&selfで読み取り参照のまま、別の型の読み取り参照に読み替えるのはもちろん、 selfで消費してしまい、確保メモリをそのまま活用して、別の型に読み替えるのが効率ええんやな
>>
http://2chb.net/r/tech/1708677472/784 Ruby (が採用している CSI 方式) での文字列オブジェクトはそれぞれどの文字コードであるかの情報を持っていて処理系は各文字コードの処理方法を知っている。
つまり文字列を扱うあらゆる箇所で様々な文字コードごとの処理をやってる。
それが先進的か?
文字コードが統一できない世界でも「なんとかする」方法だろ。
内部的には統一した文字コードで扱い、様々な文字コードを扱いたければ入出力の段階で変換するというのが Rust 的なスタイルを含む現代的なプログラムが目指すところで、そのために Unicode はあるゆる文字コードから「変換可能であること」を指向してる。
とはいえ、これが先進的と言えるわけでもなく総合的に考えて現代の事情に合うやり方ってだけだ。
様々な文字コードの変なところも含めて Unicode に取り込んでいるのは既存のテキストのデータを (情報を失うことなく) 移行できなきゃ Unicode に統一されていかないからで、同じ駄目なら統一されていないことによる駄目さより統一されてる駄目さのほうがかなりマシという価値観による。
いろんな駄目さに個別に対処するのではなくデカい駄目に皆で立ち向かう。
人間の言語が数千年・数万年の歴史的経緯の積み重ねなので文字も駄目だし文字コードも駄目。
根本的に駄目なものはどう扱ったって駄目。
綺麗なやり方で扱わないのは綺麗なやり方が存在しないから。。
ネットもファイルもUTF-8で統一しちゃうのが吉 外部のcharset=Shift_JISとか扱わないといけない分だけencoding_rs _io
>>356 >>375 >既にimpl Tにあるのだからimpl Trait for Tへ移動させるだけだぞ
pub 付いてると知名的なので doubt
crateとかdocsの事考えるとそんな単純な話じゃないんだよ 実践的なコード描いてない人か
歴史的にマクロ=悪の固定観念もってるプログラマも多い気がするから macro_rules!()はtemplate!()に改名した方がいいかもしれんね impl Traitとかマクロ使わないと面倒な場合が多い
Rustってfor_eachのclosureのなかでbreak出来ないのです
>>418 名前は Scheme の syntax-rules から持ってきたんだと思う。
>>419 map_whileやtake_whileか
try_for_eachやtry_foldを使えば?
ControlFlowを使って自分で作る方法もある
>>419 クロージャは(変数をキャプチャできる)関数の一種なのでbreakなんて概念はない
for_eachはクロージャを引数に取る高階関数なのでbreakなんて概念はない
次々とやってくる「全ての各エレメント」に対して何度もそのクロージャを呼び出すだけなのでクロージャで早期returnしようとしても全てのエレメントに対して処理される
やりたいことはおそらく次々とやってくるエレメントの途中で処理を終えたいのだろうからfor_eachではなく以下のイテレーターメソッドを使う
>>419 中断条件を分離できるならばイテレータを返してくれる(そして他のイテレータメソッドを繋げられる)以下を使うのがベター take(n) 最初のn個だけ while_some() OptionがSomeの間だけ take_while(f) fが真の間だけ その後に続きを漏れなく使いたいときは take_while_ref_inclusive(f) take_while_ref(f) peeking_take_while(f) map_while(f) 変換しながらfがSomeの間だけ scan(init_state, f) 状態を持ちながら変換しながらfがSomeの間だけ いきなり結果を(ResultやOptionやControlFlowで)返したいならば try_for_each(f) fが中断(ErrorやNoneやBreak)になったら終えてそれを返す 中断なければ()を返す try_fold(init_state, f) 状態を持ちながら同上 中断なければ状態を返す try_collect() iterとitertoolsで仕様が異なりiter版はnightlyのみだけど 中断になるまでをcollect クロージャが関数の一種なのか関数がクロージャの一種なのかそれが問題だ
大雑把な説明としては、 クロージャは(キャプチャがある)関数の一種、 関数は(キャプチャのない)クロージャの一種、 と言っても構わないが、 実際には、 Fnで使えるのはsafeなfnのみ、 fnにコアースできるのはキャプチャのないFnのみ、 といった関係。
クロージャと言えばFn(&mut T) -> ()みたいな定義が許容されてるのはなんでなの? 間違った使い方をすればownershipルールに違反してエラーにはなるだろうけどFnMut(&mut T)->()にするよう弾いたほうがよくない?
試しに見てみたがリファレンスと同じ情報の劣化版なので見る価値なし(個人の感想です) >try_for_each(): Iterator<T> -> (T -> Try<B=()>) -> Try<B=()> >失敗するかもしれない関数について for_each 的な操作を行う関数。 >これといって特記すべきこともないが、今まで for で書いていたものがシンプルにできる、ありがたい関数である。 >もし成功時にも何らかの意味ある値を返したいのであれば、 try_fold を使うべきである。 例えばtry_for_eachの最後の行の解説とか ツッコミどころが盛り沢山
>>427 クロージャの引数は、毎回変わるのだから常に何をしても自由であり、引数を消費してしまおうが、可変参照があって参照先を書き換えようが自由。
クロージャで制限がありうるのはキャプチャした値のみ。
Fnはキャプチャした値がある時に、それを読み取り参照しようが自由だが、書き換えたり消費したりはできないという意味。
FnMutはキャプチャした値を読み取り参照しようが書き換えようが自由だが、消費してはいけないという意味。
FnOnceはキャプチャした値を消費しようが書き換えようが参照しようが自由という意味。
キャプチャ値を消費をしてもしなくても自由ということは、2回以上の実行は不可で、そのクロージャの実行は1回だけという意味、だからFnOnceという名前。
トレイト間の関係は「Fn: FnMut」かつ「FnMut: FnOnce」、つまりFnOnceは他の最上位のスーパートレイト。
集合で見ると、FnOnce⊃FnMut⊃Fnとなり、Fnが最も制限がきつくて集合としては小さい。
蛇足だが、fnはさらに制限がきつくて読み取り参照キャプチャすら許容されないから、Fn⊃(safeなfnの集合)となって、safeなfnは任意のクロージャの位置で代わりに使える。
例えば、LazyLock::new(f: F)のような、1回しか指定クロージャが実行されない高階関数では、最も緩いFnOnceでトレイト境界「F: FnOnce」を指定できる。
逆に何度もクロージャが実行されるIterator::fold(init, f: F )では、初期値initは消費されるが、fがキャプチャした値が消費されては困るためFnOnceではダメで「F: FnMut」となり、fの引数二つは毎回消費できる。
>>428 一番重要な独自の分類方法を最初にまとめて書かないからクソ記事になる
>>430 >クロージャの引数は、毎回変わるのだから常に何をしても自由であり
なるほど。言われてみれば納得。
ありがとう
なんでtypescriptのソースをrustに移植できないの? プログラムなんだから不可能ってことはないでしょ?
>>433 出来ることと効果的に出来ることは別というシンプルな話。
TypeScriptのコンパイラはその利用の多さからもっと高速さを狙ってC/C++・Rust・ZigなどのGC非依存言語で書く価値がありブラウザ上Wasm実行の観点からもそうすべきだったが 担当者の能力不足のため遅いGC依存言語から速いGC依存言語へ書き換えるだけで終わってしまった そのため早くもWasmでの実行が遅いという指摘が出ている
要するに、GC依存症の人にはrustは過ぎた物って事か。
アンダース・ヘルスバーグが能力不足なんて話があるかいな。 Rust や C# が得意なのにあえて Go を選定したんだぞ。 WASM 上で遅いのは WASM のほうの性能不足だ。 Go の優秀さはランタイムサポートの作り込みにあり、それが十全に発揮されない環境ではそりゃ遅い。
Rustで書けばwasmの件も問題なかったわけだからGoという中途半端な言語を選んだ選択ミスだな~
WASM ってそんなに絶対に考慮が必要なほど重要なプラットフォームか? コンパイラを WASM 上で動かそうとする判断をするやつがいたらそのほうが選択ミスだろ。 TypeScript からの移植という前提があったから Go が比較的やりやすいと判断された。 関数単位でほとんど一対一のベタ移植を出来てる。
GC言語で書かれたプログラムをRustに移植しようとするとプログラムの構造を大幅に変えなきゃいけないからな まあRustでのプロトタイピングも絶対やってるだろうけど
スパゲッティになってる下手なプログラムは、Rustで書く時にそれをほどいてまともなプログラムにしなきゃいけないもんね それにより効率改善や機能拡張などの保守性も格段にアップするから、当たり前で必須な作業なんだけど、手間を惜しんだのかね
また的外れなことを 普段Rust書いてれば嫌でも分かることなんだけどなぁ
TypeScript で書いてあることの弊害としてランタイム (つまりは JavaScript 実行環境) がウェブ用に最適化されてることを挙げてる。 ウェブのプログラムではリクエストごとのターンアラウンドタイムが重要だが、コンパイラは時間あたりの計算量が重要で、違う戦略が要る。 コードの保守などはとりたてて問題になっていない。 もしより良く出来る余地があったとしても組織としてコストを支払うほどの価値じゃない。
Rustの話題だとダンマリなのに どうでもいい他の言語の話だと連投するヤツいつもいるな
政治や流行に流されない決断ができる土壌があるのは良い組織 動画を見るとヘルスバーグの優秀さがひしひしと伝わってくる windowsのPMとは大違い
一通りいろんな言語でプロトタイプコンパイラー作ってみたって動画内でも言ってたじゃねーか。で、Goが一番一対一で手堅く移植できる上に十分に速度アップもしたと言うことかと パランスの問題だよ。時間をかけてリターンがどれだけあるか。だって営利企業だしプログラマーは無料じゃない。実際、方針決まってからはギットハブ・コパイロットに大部分やらせたんだろうがな
なんでfirefoxのソースをrustにできないの? プログラムなんだから不可能ってことはないでしょ?
新たに作るものはRust一択になりつつあるが 既に別の言語で書かれているものはそれを負の遺産として考慮しなければいけなくなる サンクコスト効果コンコルド効果に加え既存言語プログラマの抵抗勢力も足を引っ張る要因となる
>>448 > 新たに作るものはRust一択になりつつあるが
んなこたーない。
選択肢として普通のものになったが、あくまで選択肢のひとつだ。
日本語を型付きにして文法的に正しく無い書き込みは投稿ボタン押した時点で弾くようにならんかな。必ず日本語コンパイルエラー無しなのを確認してからしか誰も会話しちゃいけないなら世の中より良くなるはず。頭の中がスッキリする。
型への幻想期は誰しもが通る そのうち人間には無理なことを悟るまでがテンプレ
状況に応じて適切な言語を選択するのが普通の技術者 特定の言語に入信して なんでRustじゃないんだなんでC#じゃないんだと 感情的にコメントを書いてるやつが多くてすごく滑稽
>>451 ちょろっと書く程度なら何でもいいけど
まともに開発するなら強い静的型付け言語が開発効率面から必須
「あると良いね」くらいじゃね DropboxもPythonだったんだから、Dropboxくらいちゃんとしたサービスのレベルまで行っても必要条件であることはありえない そしてそれよりデカいサービスの立ち上げは言語どうこうとかよりそもそもそのサービスが参入できる隙間を見つけて高速に参入することが重要。
やりたければどんな言語でも手間暇かければできるのは当たり前 強い静的型付け言語で構築しないと開発保守効率が劣り時間と労力の無駄
効率の話か それで言うと、ビジネス感覚のある人が好まない言語はそもそもビジネスが成功しないから開発するだけ無駄だな
時間をかけないためにスタートアップは動的言語を使ってるんだけどな Facebook, Instagram, Youtube, Github, Twitterと例をあげればキリがない
動的型付け言語を捨てて静的型付け言語に移行したとか 静的型付け拡張の開発を主導してるような… あと最近はスタートアップでフルスタック typescriptにしてるところは珍しくない
それぞれに適したものがあっても関連するプロジェクト全体で一貫した言語を使った方がスキルセットの管理が単純になるから運用が楽になることはある。 ウェブ系だと JavaScript か AltJS は避けられないのでそれに寄ってしまうのは仕方がない。
自分の頭で考えられない人ほど またスキルや経験の幅が狭い人ほど 特定の技術を宗教化して盲信しやすい そうなるとますます自分の頭で考えられなくなり どんな不都合な事実があろうと 教義に反さないよう都合よく解釈しようとする 優秀な技術者の対極
>>462 フロントサイドはTypeScript+WebAssemblyで良いけど
サーバーサイドまでTS/JSはリソースの無駄遣いなんだよね
もちろんまだ技術の発展途中なのでSSG/SSRをハイドレーションしてCSRするなら
その部分に限ってTS/JSでコード共通化は理解できるけどね
>>460 最も普及しているC++を消している時点で論外。
静的であろうと動的であろうと重要なのは(関数呼び出しなどの)コードの接続面・境界面の互換性であって、オブジェクト操作の互換性があれば良い。 動的型付けはこの互換性が実行時でないと判定されないのが問題であって、コード開発時(コンパイル)等に互換性を判定する仕組みがあれば問題無くなる。 コード解析は貧弱なので役に立たないが、静的インターフェイスのサポートなどで改善するだろう(今はそういうの無いけど) 静的型付けは互換性の判定のために型の命名を強制されるので、設計の柔軟性が無いなどの問題を持つ。こちらもC++コンセプトのよう静的インターフェイスで改善するので、今後は変数のコンセプト対応のようなインターフェイス改善で解決していくだろう。 RustのTrait境界もコンセプトのような柔軟性が欲しいところ。
>>458 スタートアップ時は動的型言語で造って
軌道に乗ったら静的型言語で造り治す例もあるが
>>468 さすが書き手も読み手もQiita品質
テラワロス
「トレイト境界」などという完全な誤訳をいつまで使い続けるのかね?
わざわざBoundsと言ってる意味を考えてみてはどうか 第一言語が英語の俺からすると境界で違和感ない お前は日本語が怪しいだろと言われれば確かにその通りだが
限界とか条件ならbounds じゃなくてlimitationだしな。 interface的な意味合いが強いのにinterfaceにしなかった理由はなんでかね?
>>472 英単語としてはそうかもしれんが、他の言語の用語にある interface と似た部分はありつつもやっぱり違うし、そこらへんは違う語をあてたほうが自然だと思う。
通勤電車乗ってなくてうらやましい > 目的地を意味する表現です。 例文. This train is bound for Tokyo station. この電車は東京駅 ...
>>474 それは「bound for」という熟語だし、さらに言えば
bound 境界
for 方向(対象までの間が主眼)
の組み合わせでそういう意味になるから、boundの例示で出すのは不適切かと。
inboundも外→内の境界付近のイメージが強いし、なんか良い例無いんかね。
circleじゃなくてdiskの方に適用可能範囲があるから、境界を印象付けてもしょうがない 範囲や領域って言えばいい
>>471 >わざわざBoundsと言ってる意味を考えてみてはどうか
そのセリフそっくりそのまま返すわ
本当に英語ネイティブなら日本語の「境界」の意味を知らんのだろうな
>>472 >限界とか条件ならbounds じゃなくてlimitationだしな
boundsをそのまま表現できる日本語の二字熟語は存在しないから完璧な訳語というのはない
完全な誤訳というのはあるけれども
>>475 おいおいww
bound forのboundとtrait boundsのboundはスペルが同じだけで意味も語源も違う単語だぞ
何が「bound 境界」と「for 方向(対象までの間が主眼)」の組み合わせてそういう意味になるだよ
不適切にもほどがあるかど。
inboundももちろんbound forのboundと同じでtrait boundsのboundとは関係ないからな
>>476 >circleじゃなくてdiskの方に適用可能範囲があるから、境界を印象付けてもしょうがない
これこれ
他動詞なんだからしゃーない日本語にはその概念が未導入だ この例を見てくれよ developers.google.com/maps/documentation/javascript/examples/control-bounds-restriction ニュージーランドの国境座標で境界固定されてる Restricting Map Bounds const NEW_ZEALAND_BOUNDS = { north: -34.36, south: -47.35, west: 166.28, east: -175.81, }; Rustじゃなくてタイプスクリプトだがboundって俺らプログラマーは普通にコーティングするとき使ってるから。意味もわからずニュアンスだけ知ってりゃコーティングミスしないよ
>>485 >他動詞なんだからしゃーない日本語にはその概念が未導入だ
よく意味がわからないんだがなんで他動詞だとしゃーないの?
未導入の概念というのはBoundsのこと?
ちなみにその例にあるBoundsは名詞
>>485 2D描画の文脈で使われるboundsは基本的に矩形領域のこと(3Dなら直方体の領域)
trait boundsと同じように何かを制限する範囲/領域という原義から付けられた名前だがもし「境界」と訳されてるとしたらの機械翻訳の質の問題だろう
要するに機械翻訳を誤訳と気づかず採用したんだろ プロの翻訳家は誤訳に気づいて修正したが間違いを認めたくない勢力が境界で違和感ないと言い張ってるわけだ
BoundsChecker って最近見かけなくなったな
boundsは境界で正しい 他の候補はない Type1: Trait2 Type1の取れうる型のうちTrait2がその境界となっている Trait3: Trait4 Trait3の…(同様) つまりトレイトにより境界を引いている このように各々意味が異なる 境界 bounds 限界 limitation 制約 constraints 他の例 array-bounds checking 配列境界検査 Scalaのupper type bounds 上限境界 Scalaのlower type bounds 下限境界
boundというと結び付いてる・紐付いているといった意味合い 日本語で境界というと、外と内といった「堺目」という意味合いが強い 自分はトレイト境界という表現に慣れてしまったのでそこまで違和感はないけど、訳としては不適当だと思う 余談だけどPythonとRustのFFIに使われるPyO3というクレートがあって、そこでは Bound という型が出てくる これはPythonのGILに紐付いている意味合いで、trait boundのboundと同じ意味合い
「訳がおかしい」と言ってるアホ達が代案を出さないことからも境界がぴったりな言葉 トレイトで境界を引いている
まずこのスレから「トレイト制約」で通しましょう
オライリー「トレイト制約やで」>
>>494 >>492 同志「際立ちますね」>
>>494 boundsに制約なんて意味はない trait boundsも、ある一定内の数値や、配列のインデックスなどのbounds checkingと同じく境界が定まる
訳語を探すそもそものアプローチというか考え方が間違ってるんだよな
お前らそんなに和訳やる気あんならtatsuya6502のケツひっぱたいてこいや
「制約」という違和感ありまくりの間違った単語を使っているアホどもは、 例えばあるクラスに対してその基底クラスやスーパークラスを「制約」だと捉えているのか?
トレイト境界とかいう和製英語やめて特性規定(特性を持ってますよって規定な)とかにしようや。省略しないなら特性保持規定、特性保有規定 ジェネリック型がある特性を持つという規定があるから、その特性を実装するっていう文なら自然だし
>>501 boundsに規定なんて意味はない
trait boundsはそのトレイトによって定まるトレイト境界だ
集合論的な意味での境界だな ベン図のイメージ T: EqはEqを実装する型の領域 T: CopyはCopyを実装する型の領域 T: Eq + CopyはT: EqとT: Copyが重なった領域
>>495 「制約」という単語は真逆の意味だから使ってはいけない
制約ではなく境界を引くことで能力を与えて強力になっていく視点がトレイト境界
>>505 その通り
where句がない場合
<T> ←(Anyしか)何もできない子
<T: Eq> ←Eqを使える子
<T: Copy> ←Copyを使える子
<T: Eq + Copy> ←EqもCopyも使える子
つまりEq + CopyでEqの境界とCopyの境界の両方を満たす境界が引かれる
そしてどんどん使える機能が強化されていく
つまり「制約」とは真逆のイメージなので「制約」という表現は全く合わない
トレイト境界という表現が正しい
数学だと制約に相当するんでは? 三角形の内二等辺三角形があるのは条件を満たしているものだけ プログラムも機能が充実するとイメージとは真逆で制約が強くなっていることになる 出来ることが増える=制約されてる void*ポインターが無制限で型が付くと型の制限がある
これはずっと考えていたことで今急にひらめいたとかじゃない
>>495 一般的に constraints の訳語として「制約」をあてるのでこの場合には好ましいとは言えない。
ただ Haskell で constraints と呼んでいるものと Rust で bounds と呼んでいるものに類似点があるかというとまあ結構あるとは思う。
二つの辺の長さが等しいと言う制約のと ○○という関数を持っていると言う制約
>>494 ブランチを切るで暴れてた人ですねわかります
>>501 そんな理由だったら単に「定格」でいいわ
カタカナでいいんじゃないかw 英語見た場合に納得できる
こういう時は何故かHaskell = 圏論勢が出てこない
>>506 英語版の Rust book だと「型やライフタイムの使われ方を制限する (to restrict) 」とあるよ
Trait and lifetime bounds provide a way for generic items to restrict which types and lifetimes are used as their parameters.
数学とかプログラミングと関係ない、普通の言葉としての bound は元は「紐で縛る」から来てる
制限、制約、境界といった意味はそこからの派生
そもそも
>>506 だって制約だと思う
ジェネリクス関数の中で呼べるメソッドが増えることに注目してるようだけど、利用側から見ればその関数に渡せる型について制限が増えるでしょ
>>515 それはおかしい
トレイト境界の対象は型
最も制約の多いAny状態を出発点として
トレイト境界を増やせば増やすほど型が機能できる自由度が増えていく
>>516 逆
三角形が二等辺三角形のみに限定されて自由度が増えてると思うか?
これが制約だと思えない人は数学的な素養がない
機能実装=制約 情報量が少ないのが自由度が大きくなりがち 確率だとしても明日の天気の状況が全くわからないとすると何の制約もなく平等に各状態がある 天気予報などから明日は降水確率70%などと情報を得ると確率がかわり偏る 情報学で言うエントロピーが増大した状況 ビットの0と1が等しい確率で出てくるような何ら情報の無い状況がエントロピーが少ない
>>516 void * はなんでも渡せるが逆は出来ない
trait もそうで増やせば増やすほど渡せるものが制約されていく
>>517 用語にいちいち反対している人は
AIに質問して還って来た答えを
ここにコピペしてるような臭いがする
>>521 それは真逆の視点だから真逆の結果となっている
型に対するトレイト境界なのだから型の視点で見るべき
トレイト境界がAnyしかない初期状態が最も制約されていて機能がほとんど使えない不自由な状態
そこからトレイト境界を増やせば増やすほど実行できる機能が増えて自由度が増していく
自由度なんて何も考えなくても理解出来るだろ… 思い込みを直す機会だぞ なんなら大学に行って数学と情報学を学べばいい
>>522 「トレイト境界」という状況を最も的確に表していて正しい訳に対して
なぜ反対しているのか?
>>524 CSを学ぶべきは君だろ
「トレイト制約」派は本質を理解できていないから「制約」なんて間違った用語を用いてしまう
>>526 学生と言うクラスに対してそれが三角形なのかと言う問いはおかしく見えるが
学生であり三角形でもある可能性もある
トレイトが実装されていなくても同等の機能が実装されている可能性もある
一概にトレイトが実装されているから高機能であると言う論は当てはまらない
ある機能を使う場合に対象となるものがトレイトを実装されているものに限定されているだけ
これはただの制約でしかない
トレイト境界 トレイト制約 トレイト要求 トレイト条件 トレイト限定 whereでトレイトを限定しているので指定の自由度は低くなっている
>>527 プログラムを書いたことないのかな?
impl Display for T した時にそれはDisplay機能を追加したのであって制約したわけではない
fn foo<T: Display>() した時もそれはDisplay機能を追加したのであって制約したわけではない
もちろん逆の視点で見れば制約になるのは当たり前だが逆の視点で見る必要がない
普通の視点ではDisplay機能が増えて利便性が上がったと解釈する
その機能を持つ線引きとしてトレイト境界がある
これをトレイト制約と訳すのは違和感ありまくりの間違いだ
>>528 わざと逆方向の視点で語ってるだろ
まともな視点では使える機能が増えている
制約ではない
>>529 トレイト境界について話をしてるんだけど?わかってるか?
トレイト境界は制限でありある種の束縛である
>>530 わざと馬鹿な振りしてるのか?普通に馬鹿なのかどっちなんだ?
トレイト境界 訳語でぐぐったら出来たぞ
https://github.com/rust-lang-ja/book-ja/issues/172 > その型がとりうる値を制限し、より具体的な型を定義する
制約を含んでいる
>>531 真逆の視点で見れば制約と解釈できるのは当たり前
しかしそんなバカな視点持つ人はいない
デフォルトとAnyトレイトしか使えない不便で制約が最大の状態から
各トレイト境界により各トレイト機能を使えるように制限を解放していくのがトレイト境界のプログラミングほ本質
「トレイト制約」派は頭がおかしい
>>534 相手に対して決めつけたベン図的な考えをしてるのが間違い
自分はトレイト制約にしろとはいってない
ただトレイト境界は制限を含んだものだと言ってる
自由度が低くなると言っている
トレイト境界で自由度が高くなると言うポンコツと意見が対立するのは当たり前
学生であり三角形の可能性としては 名前が 三角 形さんである場合が当てはまる その人は学生であり三角形
>>498 これに触れちゃったから真っ赤になっちゃってるね
>>534 もしかして impl X for Foo のように「トレイトを実装する」ことを trait bound と思ってる?
trait bound は「この関数に渡せる型Tは〇〇を満たさなければならない」の意味だよ?
Tとしか書かれてないジェネリクス関数は文字通り「何でも渡せる」から、これが一番制約が少ない
>>535 何度言っても理解しようとしないやつだな
非現実的な視点としてそこでは使わない非該当な型からみれば、その型は使えないのだから制限となるのは当たり前だ
そんなプログラミングとかけ離れた非現実的な視点でみるのはおかしい
プログラミングの視点では各トレイト境界を増やすことでその関数でできることが増えて制限から解放される
>>538 その真逆な視点から見れば制約になるのはの当たり前だとずっと言ってるだろ
どちらを制約と捉えるかの問題
Anyしか何もできない<T>が最も制約されている状況
それに対して<T: Trait>とトレイト境界を課すことで制約がなくなって使える機能が増えていく
>>539 トレイト境界に対しては真逆だろ
プログラミングの視点で見てもトレイト境界を増やすことで制限が増えて対象への制約が増える
実装でトレイトにあたる部分を使用しているかどうかはどうであれ自由度が減る
こんな当たり前のことすら理解できないのか?
あえて造語すれば機能域とかになるのかな 制約とか機能が増えるとかは視点によって出てくる結果だろう
>>541 その180度逆の視点で見れば制約になるのは当たり前だがそんな視点でプログラミングは行われない
「トレイト境界」により「制約された」とは考えることはなく
「(制限されてる状態から)使える機能が増えた」と考える
>>542 その通り
視点によって両方が起こる
だからそこ「トレイト制約」ではなく「トレイト境界」が正しい
各トレイト境界により線引きされて境界が定まるだけ
それにより使える機能が増えて便利になることがプログラミングの本質
制約されて不便になったとは考えない
>>543 脱線になるが自由度の意味が判ってない
三角形なら基礎的なルール(三つの角度を合わせると180度など)守っていれば辺の長さや角度は自由に設定できる 自由度が高い
二等辺三角形は二辺の長さが同じと言う制約がありその他にも角度が制限される 自由度が低い
二等辺三角形は自由度が低いがそのために角度などを利用して他の隣接した線分などとの角度が確定できるようになる
自由度は減っているが他から見ると利用価値がただの三角形から上がってる
制限なしの型パラメータを制限してるだけでしょ <T> ←制限ナシ <T: Eq> ←Eqで制限 <T: Copy> ←Copyで制限 <T: Eq + Copy> ←Eq+Copyで制限 制約って言ってる人の感覚のほうが俺も近い (型パラメータの型を)制約ってことでしょ > 使える機能が増えて便利になることがプログラミングの本質 そんな主張生まれて初めて目にしたわ正直w
自由度すら理解できないなんて この人いつもの長文でおかしなRust擁護書いてる人かな?
>>546 その真逆の不自然な視点を取ることももちろん可能だが
普通はこちらの視点
<T> ←(Any以外)何もできず制限最大
<T: Eq> ←Eqが使えるようになる
<T: Copy> ←Copyが使えるようになる
<T: Eq + Copy> ←EqもCopyも使えるようになる
制約を増やしているのではなく
機能を増やしている
だからトレイト制約なんていうバカな呼び方を採用しない
>>547 偏った片方の視点でしか見れない可哀想な人だな
まずは視点を変えることで2つの真逆な見方があるという当たり前のことを理解しようね
型を制限してるんよね 機能がどうのこうのの以前にね これって理解するの難しいのかなあ
>>549 トレイト視界なんて意味不明
トレイト境界を増やしていくことでその型の使える機能が増えていく
そこで各々のトレイトに境界という線引がある
>>551 そんな当たり前のことはわかってると何度も伝えてるだろ
その片方の視点でしか考えられない狭い考えの人が「トレイト制約」という間違った用語にこだわっている
>>548 vec<T>
vec<T>:where T Eq
vec<T>:where T:Copy
vec<T>:where Eq + Copy
自由度が高いvecはどれ?トレイト境界で自由度が増えるなんて馬鹿はいない
>>554 二つの視点を理解できた?
さらにその問題ならVecの視点とTの視点でさらに二つ分かれる
もちろんトレイト境界はTに対するものだからTの視点が普通人の視点
トレイト境界が何もなければTに対して何もできないから一番不自由な状態
「自己責任」の語源という噂もあるIT界隈ってやっぱ最先端なんだな 自由と制約 性善説と性悪説 なんでもITで定義できる
<T: Eq>で考えたとき 「: Eq」はどこにかかってんのか? 「T」でしょ、それ以外ではないでしょ? で「T]は何かっていうと型でしょ? この話のどこに「機能」とやらが出てきたの? 片方の視点もなにも、そもそもの話が
まだ自由度すら理解できないんだよな 文系プログラマの末路が見える
>>557 各トレイトは各々の特性という機能を宣言している
Tという型が何をすることができるものかをトレイト境界で指定していく
ちなみに何度も言っているが
Tという抽象型自体の視点ではなくて、Tに入りうる具体型候補の集合という裏の視点で見れば、トレイト境界が制約になることはもちろん理解している
そんな偏った視点で考えるのはおかしいと主張しているだけ
だから「トレイト制約」というアホな用語は絶対に許容しない
>>559 恥ずかしながらそれ読んだことなかったw
> Trait and lifetime bounds provide a way for generic items to restrict which types and lifetimes are used as their parameters.
> 特性と有効期間の境界は、汎用アイテムがパラメータとして使用される型と有効期間を制限する方法を提供します
はいこれ
型を制限なのです
>>560 >>506 > 「制約」という単語は真逆の意味だから使ってはいけない
言った通りだろ T自体ではなくTに入りうる具体型候補の集合で考えればもちろん制限になる
>>563 その通り
トレイト制約という不自然な用語を採用するつもりは絶対ない
トレイト境界 機能:型を制約します その一方で 「トレイト制約は不自然だ~」 これは無いな
>>566 まだ二つの視点を理解できないのかね?
トレイト境界は
機能を強化する側面と
具体型候補を制限する側面がある
互いに裏返しでどちらも正しい
その線引をしているから境界
>>567 bound が「線引き」だとして、例えばRustコンパイラが出す以下のメッセージはどう訳すの?
Error: the trait bound is not satisfied
「制約を満たさない」からエラー、という方が自然じゃない?
>>568 文字通りにトレイト境界を満たさないだよ
例えば具体的に Error: the trait bound 'TypeA: TraitB' is not satisfied と指摘される
つまりこのトレイト境界を満たさないとは
TypeAはTraitB(の機能)を実装していない、という意味
「トレイト境界」という言葉が既に用語として認識されている感はあるし、「トレイト境界を満たさない」と書いても実用上は伝わると思うけど 「境界線を満たす」のように、satisfyの目的語が線になることはないと思う
>>570 線だとは誰も言っていない
線引をして境界を構成しているわけなので、線ではなく境界
だからトレイト境界(trait bound(s))という用語が英語でも日本語でも正しい
imple S {} を全面的に禁止して imple T for S {} だけしか使えない環境にするべきだったね
>>571 クラスもインターフェイスもトレイトもそのままが良いと思う
>>573 トレイトは異なる型の共通機能に対して共通処理をしてコードの共通化をするためにある
そのコード共通化で必要となる共通機能をトレイト境界として列挙する
各型の独自の機能についてトレイトを設ける必要はない
>>572 >>567 の最後の行で (trait bound は) 「線引きをしている」と主張してない?
>>575 線引をして境界が構成されるんだよ
だからトレイト境界と呼ぶ
二項演算を使いたいだけなのに単位元の定義を強制されるパターンはたまにある 制約がないと言えるのは、使いたい関数の名前とトレイトの名前が同じやつだ
なんか伸びてるけどトレイトのようなものは他言語でもよくあるでしょうに ジェネリックくらいちゃんと理解しとけ
>>578 Javaのジェネリクスどうなってるかなって見てみたら
https://docs.oracle.com/javase/tutorial/java/generics/boundedTypeParams.html > Bounded type parameters are ...
> ..., use a type parameter bounded by the Comparable<T> interface:
Bounded type parametersって呼び方なんだな
制約と言う人達は trait を理解していない C++03からやり直すべき
>>582 このスレで出てる話は trait でなく trait bound という言葉についてだぞ
>>570 日本語では「境界を満たしていません」なんて言い方はしないんだよ
質の悪い機械翻訳以外ではね
現代日本語の「境界」は境界線や境目のことであって境界づけられた範囲や領域を指して「境界」とは言わない
“bound is not satisfied”や”requird by this bound”などからもわかるようにRustを開発してる中の人も明らかに制約面を重視してboundsという用語を使っている
それだけじゃなくtrait boundsはジェネリックの型パラメーターの型制約の一種
ジェネリックにおける「型制約」という用語はRustに限らずプログラミングの概念として広く定着しているものでRustでももちろん使われている
それらを完全に無視して無理のある「境界」という訳語を当ててこじつけ解釈を続けるメリットは何もない
trait は特性を表現するのみで それが何かを制約することはない trait bounds はある特性の範囲を表現するのみで それが何かを制約することはない これで理解しないならお手上げだ
>>496 >boundsに制約なんて意味はない
>trait boundsも、ある一定内の数値や、配列のインデックスなどのbounds checkingと同じく境界が定まる
制約という意味はあるよ
辞書にものってる
制約という訳語がそのまま載ってない辞書でも制限や許容範囲という訳語はあるはず
制限と制約は微妙に違う単語でニュアンスも違うけど状況によっては代わりに使える単語
英語でconstraintとrestrictionを使い分けるのに似てる
type restrictionとtype constraintのどちらが伝えたい意味に近いかという話と同じ
伝えたいニュアンスとは別に「型制約」という概念・用語がかなり昔から広く浸透してることを考えるとトレイト制限とトレイト制約を比べれば後者のほうがより適切と判断するのはごくごく自然なことだと思う
>>586 >trait bounds はある特性の範囲を表現するのみで
>それが何かを制約することはない
型パラメーターが自由に動ける範囲を制約するもの
そもそもboundsは単純な「範囲」という意味ではなく何かが許された範囲・領域のことで制約・制限的なものが必ずついて回る
「境界」という言葉のほうを軸にするなら満たす/満たさないではなく越える/越えないと言ったほうが自然かなとは思う。
でも技術用語は不自然なくらいで良いとも思う。 下手に日常用語の意味と合わせると仕様上の意味と日常の意味が混ざって混乱する。 「Rust 用語ではこういうんだよ!」で行くべき。
T: Traitは未知の型Tに対して可能(必要)な操作を明示するためのもので Tの型に制限がかかるのはその結果にすぎないよ Tの型を制限する目的で境界を設定してるわけではない これはジェネリクスを含む型とか関数を実装する側になれば分かる できるだけTの制限が緩くなるように配慮しないといけない
Scala目指すのか。コップ本は挫折したな。共変半平
>>584 boundsに制約の意味はない
何らかが有効な境界や限界を意味し
もしくはその境界線や境界面
もしくはその範囲や領域を意味する
そこに制約(constraints)という発想や概念はない
trait boundsも同様
ある型やサブトレイトに対してそのトレイトが境界となる
敢えて境界(bounds)という単語を用いており
訳語もそのままトレイト境界が望ましい
cargo test --test-threads=1 でシングルスレッド実行出来るけど テスト用のプログラムの中からシングルスレッドを強制する方法は?
例の爺さんまだ頑張ってるの? その時間の使ってコードでも書けばいいのに
>>592 リファレンスには制限するためのものだとはっきり書いてあるよ
Trait and lifetime bounds provide a way for generic items to restrict which types and lifetimes are used as their parameters.
https://doc.rust-lang.org/stable/reference/trait-bounds.html もうこれで終わりかな?
1) interfaceは境界
2) traitsはinterfaceに似たようなもの(although with some differences)
3) トレイト境界=頭痛が痛い
https://doc.rust-lang.org/book/ch10-02-traits.html > Note: Traits are similar to a feature often called interfaces in other languages, although with some differences.
トレイト制約に決定したね ここからは踏み絵フェーズ 正しくトレイト制約と言えない人がリアルでもヤバイ人 際立つ言動はネットだからと思うかも知れないが、Linuxのごたごたで明白になった通りリアルにゴロゴロいる
決定も自己責任でいいんだよ自己責任で 決定の権限をコミュニティに握らせるな
>>601 オライリー「せやからトレイト制約やで」
>>598 なんか最初のパラグラフだけで「もうこれで終わりかな?」とか言って読むの終わりにしてそう
リファレンスは全部目を通した方がいいと思うけど英語は最初のパラグラフ大事だから判断が難しいな
一応次のパラグラフも載せとく
Bounds on an item must be satisfied when using the item.
When type checking and borrow checking a generic item, the bounds can be used to determine that a trait is implemented for a type.
>>600 boundsに制約の意味はない
トレイト制約は間違い
もはやお手上げだ K&Rからやり直すことをお勧めする traitを制約に使うことと traitが制約であることは 全く別なのだ この説明でもわからんのかな? テキサスの小学生でもわかりそうなもんだが
>>606 ジェネリックパラメータの取りうる範囲が
trait boundsによって制限されるだけであって
トレイト制限やトレイト制約という表現はおかしい
この違いが重要
trait boundsは
トレイト限界か
トレイト境界なら正しい
トレイト境界で良いと思う
>>606 まさかの制限派出現嬉しい
境界、制約、制限の中で一番平易でヨシ
トレイト境界 機能:型を制約します ライフタイム境界 機能:コンパイラに寿命を示します
>>611 どこにも記述されていない制約という言葉を唐突に持ち出してる人?
トレイト制約では根拠もなく意味も通らない
>>614 ,615
既にある
オライリー プログラミング Rust「トレイト制約」
トレイト制約は天下のオライリー本での訳語なので5chに限らずSNSやgithubで普通に提案できる
>>616 だから根拠を示しなさい
制約に該当する英語すら見当たらない
[0、9)という半開区間があったとして これを数値範囲の制限に使ったとしても 半開区間を制約とは言わない 半開区間で示される数値の範囲を制約に使っただけである これで理解できるか?
>>621 それは通常 bound と呼ばないものを持ち込んで無理にこじつけてないか?
凡俗法則だっけ? どうでもいい話題ほど盛り上がるってやつ
>>616 が誤解している可能性と
オライリーの質が落ちてる可能性と
二つの可能性が存在する
trait boundsはそのトレイトによる境界・限界・領域を表している そこには制約の概念も意味も一切ない そのtrait boundsによってパラメータの取り得る範囲が制限を受ける 以上の二つの事実を混同して trait boundsをトレイト制限と呼ぶのはおかしい ましてやトレイト制約と呼ぶのは論外
https://github.com/rust-lang-ja/book-ja ここ見てみたらそもそも最初はTatsuya Kawanoって人がいきなり書いた文章よね?
「トレイト境界」ってのは
それ以前にrustコミュニティでこの用語定義されてるの見たことある?
誰かrustの歴史に詳しい人ー
>>628 そのissueで議論されている
・既に多くの人たちがブログetc.の記事でトレイト境界と書いていた
・Scalaでもboundsは境界と訳している
・配列のbounds checkも境界チェック
・制約と訳される場合は英語がconstraint
わかった何がモヤってたのか
CならJIS規格があって用語も定義されてるからそれに倣えばいい
Javaなら開発元がご存命のときに日本語のドキュメントはすでにあったんでそれに倣えばいい
Rustの場合は現時点では規格が無いんよね
規格があったらそれがなんであれ書いてある用語に従うよねみんなが
>>628 それだけ?
規格が重視されなくなったのは多分CPythonがCでライブラリを大量生産した歴史のおかげだ
trait boundsの概念の理解を間違えて「トレイト制約」だと誤認してしまった人は
>>627 で指摘した二つの話を混同している
おじいちゃんはいつも一人でわあわあ言って泡吹いてるよな トレイト境界 機能:型を制約します
「型を制約します」って言い回しとして変じゃない? 「型”に”制約を課します」だったらまだ理解はできる。 もっとも制約を課してるわけではないので、この言い回しも適切ではないと思う。
じゃあ何だったら気に入るんだ? 型を限定しますか?
「型の境界を明示する / 明確に示す」とか? これが適切かどうかはわからんけど。
>>630 それはそう。
その上で、
>>628 は実質的に規範の地位を確立してるからもう妥当性を検証するような段階は過ぎてる……と認識してる人とそうでない人がいるんだと思う。
出来の良し悪しを言うやつも多いがそんなことをいったら JIS だってたいしたクオリティじゃないし、それでもなお規範という「ことにする」ということで納得しないとしょうがないんだけどなぁ。
>>635 ご丁寧にありがとうございます(
>>629 さんもあらためてありがとね)
https://qiita.com/_Nnwww/items/529ad0397e4b3a59da67 > ジェネリック関数は'トレイト束縛'と一緒に使えば最高に便利になります
初めて目にしたけど
正直良いやん!って思った
トレイト束縛
最初はこれだったんやね
倫理的な「殺すな」「盗むな」等に比べて、言語的な規則が実在すると何故そんなに信じているのかが分からない どっちも存在するか、あるいはどっちも存在しないと考えるのが自然ではないかね
>>639 束縛は変数束縛とかで使うニュアンスがすでに定着しているので違和感を持つ人が多いと思う。
>>639 それ以降も訳語を変えてはどうかという話は何度も出ているけど
結局のところ誰も説得力のある代案を出せなかったからそのままになっている、って感じ
確かrust-jpのslackでもいろいろ議論はあったと記憶しているけど
slackの過去ログは消えたので詳細は分からなくなってしまったね
日本における Rust 黎明期から特に翻訳に取り組もうとした人たちが相談して決めたことより自分のほうが妥当だと思える感性が信じられない。
>>645 どこの馬の骨ともわからん有志が対した議論もせずに
JavaやScalaの誤った訳か機械翻訳を間違って採用しただけだろ
しっかりした議論が残ってればもう少し違う見方もできるけど
これに関してはどのイシューひどいじゃん
武器などの物体は正義でも悪でもないとよく言われる それを買ったただの消費者が正しさに寄与する ただの消費者のほうが正しい、ではなく、正しさに寄与するのは消費者だけなのだ
ぶっちゃけそれ系の訳の問題言うならあれvariantが列挙子って訳になってるのをまずやめてほしい
>>639 trait bounds自体は束縛や制約という意味を全く含んでいないため
そのトレイト束縛という日本語訳はよろしくない
trait boundsのboundsの意味から有り得る日本語訳は
トレイト境界
トレイト限界
トレイト限度
トレイト範囲
つまりトレイトによる空間の線引きといった概念を表している
つまりtrait bounds自体には制約や束縛といった概念は全く含まれていないためそこは明確に区別する必要がある
そしてtrait boundsによって型パラメーターが制限される(restrict)
このような関係なのでtrait boundsに対してトレイト制限という日本語訳ももちろんよくない
トレイト境界が型パラメーターを制限する関係
Type: Traitの二項関係をsubtypingだと解釈すればtrait boundはlower bound(下界)を宣言していると見ることもできなくはないけど でもsubtypingじゃねーから微妙に惜しいんだよな 線とか言ってるのはただのバカ
>>651 そこまで理解していながら
空間を線引きを線だと思ってしまった?
線引きは概念だから少なくとも空間に対する線引きは線と無関係
有界を引き起こす存在と表現した方がお気に召す?
どちらも譲らないから延々このネタで盛り上がっていいんじゃないの 昔のム板では「importは輸入という訳語がいいかカタカナでインポートがいいか」ってレスバに花が咲いて何ヶ月も揉めたことがあるよ あんときもアレコレ英語の語源とか意味とか出てきてみんな楽しかったなあ 英語ネタというか翻訳ネタはいい意味でプログラムの本質の理解度を試されるから、ム板ではアルゴリズムそのものより熱く語られる伝統がある
ちゃうちゃう バカでも参加できる話題だから盛り上がるんだよ
まだ出ていないようなので 【「トレイト制約」と呼んではいけない理由】 プログラミング言語で広く確立されている用語として「型制約 (type constraint)」がある これは各言語によって様々な条件を指定することで型(パラメータ)を制約することを指す つまり型が制約される対象である もし「トレイト制約」という用語を用いるとトレイトが制約される対象となってしまう そのため英語でもtrait constraint (トレイト制約)という用語を用いていない trait bound (トレイト境界)は条件側の一つである
https://ejje.weblio.jp/content/bounds 日本語WordNet(英和)での「bounds」の意味
ものの限界または範囲を示す線あるいは面
EDR日英対訳辞書での「bounds」の意味
リミット;切り;埒;限り;方図;限界;限度
日英・英日専門用語辞書での「bounds」の意味
上下限,範囲,限度,限界
斎藤和英大辞典での「bounds」の意味
制限;範囲;極限;際涯;構内;切り;程;極際;限界
Weblio英和対訳辞書での「bounds」の意味
埒, 埓, 上下限, 境界, 限度, 果てし, 際限, 限り, 程
限り, 範囲, 限界, 〈際限〉・切り, 〈限度〉・程, 際限, 〈限界〉・極限, 限度
領域
バウンズ
そういや、日本語訳に文句のある人は最新のthe book の翻訳はしないの? 旧日本語版は情報が古いし公式からリンクを貼られているgithubのは翻訳している気配無いし。翻訳が間違っているなら、最新版の翻訳を用意すれば正しい方向に誘導できるんじゃないのかね。
境界がイメージしにくいとかじゃなくてboundsと言うワードが機能をうまく表現していない boundsの訳を一生懸命模索してもそこがネックになる 訳語を離れると機能面で制約や限定などになる
>>660 テクニカルタームはそういうもんなんだってば。
Rust ではこういう意味だと定義したならそれでいくしかないの。
自分は別に境界でも良いと思う でも、理解しにくいとか納得できないと言う声が大きいならそれに対しても対応しないと ユーザーが伸びない
bounds という単語に縛られすぎているw のかも 英語の方でも、ある概念を表すのに不十分ながら敢えてその単語を当てているということもあるだろうから 単語の訳にこだわるよりも概念の方にこだわるべきで、それを表す日本語の候補を挙げて適宜使い分けるとか あるいは造語するとかした方が良いのかもね
トレイト境界よりも良い候補がないんだよ
ちなみに
トレイト制約だけは
>>656 の理由で使用禁止なので
トレイト限定 トレイト固定 トレイト制約 トレイト条件
where ~だからトレイト句 トレイト節で良かったのになあ もともと英語からしてしっくり来てない人もいるのでは
>>665 >>666 型制約や型制限や型限定をするために使われる側の話だから
トレイト制約やトレイト制限やトレイト限定は全てダメ
トレイトを限定(制約)していない
それはあなたの乾燥()ですよねとしか 実際に制限され限定され固定され制約されているんだけど
parameterを媒介変数って訳したのも誤訳だと思います
>>650 >trait bounds自体は束縛や制約という意味を全く含んでいないため
制約という意味は含まれてるよ
辞書的にもboundsの和訳として「制約」が使われてるものがあるし
文脈的にもtrait boundsは型制約(type constraints)の一つの方法だから「制約」と訳すことに大きな問題はない
束縛はbindの過去分詞のboundから取ってるもので
これは同じスペルの違う単語なので「境界」以上にやめたほうがいい
将来的になんらかの機能が拡張されて制約が生じるのがトレイトだけで無くなった場合どうするんだろうかとは思う
>>671 型制約は型を制約するんだよ
トレイト制約はトレイトを制約するわけではないから誤解を招くでしょ
だからトレイト制約(trait constraint)という表現は英語版でも使われていないの
>>650 >そしてtrait boundsによって型パラメーターが制限される(restrict)
>トレイト境界が型パラメーターを制限する関係
実装すべきトレイトを指定することで型パラメーターが取れる型の範囲を制限するのがtrait bounds
型パラメーターを制限するという意味を持たないのはあくまで”指定するトレイト”であってboundsにはすでに制限という意味が付随してる
これはboundsという英単語がもともと持っているものでもありtrait boundsでもその意味が付随している
>>674 根本的な違いを理解しようよ
型は制限(制約)される側
だから型制限や型制約と言われる
トレイトは制限(制約)する側
だからトレイト制限やトレイト制約とは言わない
Cで言えばvoid*をint*へキャストしてint変数を四則演算可能にする概念をboundsと呼んでるようなもので 型で制約するためにメモリ上へ境界を作ってると解釈してるわ Rustはんではそないに呼びはりますか、どないでもよろしおすレベルなんだが、 メモリやストライドの意識がないとこんなんで盛り上がれるんだな
>>676 それは全然違うぞ?
メモリ空間とか関係なく、コンパイル時の制約として使ってるだけ
例えば C++ の const なども「可変な操作を禁止する」けど、これはあくまでコンパイル時にチェックされるだけで、出力されるバイナリや実行時の動作には影響しない
>>673 「トレイト制約」とするとトレイトを制約するものなのかトレイトによる制約なのかわからないというのはその通り
これは助詞的なものを省略して名詞化した場合に必ず発生すること
こういう場合は一般的に使われる「〇〇制約」という用語が〇〇が制約される対象という意味で使われているのかそれとも〇〇によって別の対象が制約されるという意味で使われているのかを考えるとよい
もし後者の意味ではほとんど使われていないなら問題となるが現実はそうではない
むしろ後者の意味で使われることのほうが多い
逆に「トレイト境界」のように「〇〇境界」という用語は
一般的にはある〇〇と別の〇〇の境界という意味で使われることがほとんど
つまりトレイトとトレイトの間の境界線と解釈されやすい
>>677 言葉足らずだったね、そりゃそうだ
あくまで言語設計側のネーミングセンスと概念把握の方法の話をしている
さすがに現代の言語でメモリモデルに即した名前付けをしてるとは思ってないわ
このスレでは一人だけ勘違いしてるのはID:OYB6I5YT
英単語のboundsには何かが許された範囲や領域のことで 境界線じゃなく内側のエリアが意味の中核 ただout of boundsやbeyond boundsのように 範囲の外に出てしまったこと表現している場合は 境界・境界線・限度のように面ではなく線で捉えても 実質的に問題がないから辞書にはその手の意味が列挙されている そうじゃない文脈で境界・境界線の意味を伝えたいなら boundsではなくboundaryを使う
トレイト界限でいいんじゃないの 台湾語でも領域の境界を表すというふうに翻訳してたぞ? 界(領域・範囲)の限(端っこ)なんだからもうこれで通じる
正確にはこうだ 特徵界限 使用泛型時,您通常會需要該型別實作 某些特徵,這樣才能呼叫該特徵的方法。
パラメーターTが条件で制約されている 皆は条件の方を見ている トレイトが条件となりTが制約されていると言うことは理解している 誰かはパラメーターTの方を見ている そしてトレイトが制約されてはいないと言う もちろん誰もそんなことは言ってない こちらは誰の目から見ても自明なのでそこを言ってるんじゃないと誰でも理解出来る そこを明言しても不毛だから 皆はトレイト "で" 制約と理解しているが 誰かは意図的にトレイト "が" 制約されていないと永遠に繰り返す 話すだけ無駄
>>682 界限は日本語だと使われない言葉なので
トレイト有界がいいんじゃないかな
トレイト有界により型制約をする
仮にここのレスバで「トレイト制約」が勝ったとしてさ、これから実生活で「トレイト制約」使うの? そして同僚に「なんでトレイト境界のことトレイト制約って呼ぶの?」って言われてこのスレ引用するの? キチガイじゃん
ちな
>>658 の集計
5 限界
5 限度
3 際限
3 限り
3 範囲
3 程
3 切り
2 極限
2 埒
2 上下限
1 領域
1 際涯
1 構内
1 極際
1 果てし
1 方図
1 境界
1 埓
1 制限
1 リミット
1 バウンズ
1 ものの限界または範囲を示す線あるいは面
>>686 勘違いのトレイト制約は絶対にあり得ないからその心配は必要ないかな
>>688 どれが勝ったとしても、公式じゃない呼び方する奴はキチガイだよ
トレイト制約はオライリー本がソースなのが強いね 一方でトレイト境界はボランティア翻訳みたいなのがソースだから
boundsに限界の意味はあっても制約の意味はないからトレイト制約は論外でしょ
そもそもtrait boundという英語自体が疑問符の付く表現なので日本語での100%正しい訳語を求めようという試みが徒労なんじゃな
今はRust本もたくさん出ているから多数決でも取ればいいんでは とりあえず手元にある技評のは境界だった まぁボランティア翻訳やってた人達が書いているから当然ではあるが
技術的な仕様書の類は直訳が普通。 原本が絶対だから不審があるときには原本を調べやすいように対応付けを明らかにすることが意図されている。
チュートリアルの類は仕様書の習慣に合わせるのは良くない部分があるけど、仕様書と違う用語を使っちゃったらそれはそれでおかしいしな。
>>692 trait boundはビッタリな適切な表現なのでそこを問題視する人はいないよ
元々boundは数学での基本用語でそこからプログラミング言語でも使われている
数学ではT⊂Uで任意のt∈Tに対してt≦x, x∈Uとなるxをupper boundと言う
Scalaでupper type bound (上限型境界)『T <: U』とは型変数Tが型Uのサブタイプであることを示す
Rustでは『T: U 』で型パラメータTがトレイトSのトレイト境界(trait bound)を示す
つまりtrait boundは概念を上手く表している良い用語
あとはboundの日本語訳だけど上述の他の言語でも境界と訳している
他にもプログラミング界ではbound checkingを境界チェックまたは境界検査と訳している
>>698 トレイトが実装されていなければout of boundsと呼んでしっくりくるんならわかるけど
そうではないだろw
違和感しかない
>>698 数学用語は境界じゃなく界
それを間違って境界と訳してしまったのはScala関係者の罪
界であれば単語の持つ意味的には境界のように間違いというわけではないがトレイト界やライフタイム界とするとやや専門的過ぎて界と言えば相撲界や芸能界のような業界を連想する人たちを遠ざける
arrayのbound checkはindexが”妥当な範囲”の中にあるかどうかをチェックするもの
この”妥当な範囲”を示す便利な短い単語が日本語にはないため”妥当な範囲”という本来の含意を捨てて実質的に問題が発生しにくいと思われる意訳を行っている例が”境界検査”
Rustで単なるboundsは対象が明白な場合の略の場合とtrait boundsやlifetime biundsやuse boundsの総称として使われている use boundsはこの前入ったprecious capturingね fn capture<'a, 'b, T>(x: &'a (), y: T) -> impl Sized + use<'a, T> { (x, y) } いずれにせよboundsはRustにおいても長く定着して使われている基本用語なのでこれを批判しても意味がない bounds1 + bounds2 + bounds3 と境界が複数あるとその共通部分に入るイメージ
トレイトを使った型制約なので「トレイト制約」 リファレンスやエラーメッセージでboundsと一緒に使われている動詞を見ればコアな開発者もboundsを満たすべき制約/条件/要件という感覚で使っていることがわかる bounds must be satisfied type must meet the bounds relax the bound 「境界を満たす」とか「境界を緩和する」とか日本語でも英語でも言わない
オライリーだけでなく吉川邦夫氏は詳解Rustプログラミングでは「トレイト境界」を使っていたがRustプログラミング完全ガイドでは意味がわかりやすいという理由で「トレイト制約」に変更している 今のところオライリー以外でプロが翻訳してるRust関連本は吉川邦夫氏によるものだけだからプロが出した結論と言ってもいい Comprehensive Rustの有志翻訳も「トレイト制約」を採用してる
なるほど 少なくとも「自転車置き場議論」と見做す向きはこの新潮流に合流出来るね
boundの本来の意味を尊重するなら制約より制限だな せめて「限」の字は使いたい
全体の日本語訳の出来を比べればどちらがいいかは火を見るより明らか
専門用語は無理に訳さんでもいいのにな 訳したら対語表欲しい
ここまでで分かったことは、日本語には訳さずそのままtrait boundと言っておけてことだな。 うっかりトレイト境界って言おうものならオライリー教の狂信者が顔真っ赤にしてシュバってくるし。
c#のdelegateがデリゲートだったり
ほかにもclosureは単にクロージャって呼ばれてたり
同様にファンクタ、ラムダ式とかも
カタカナに置き換えるくらいが解釈の余地を挟まないから良いのかもね
https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/delegates/ Rustのusers forumでも数学でのboundsのようなものと説明があるね つまり制約ではなくて境界や限界それらによる範囲を表しているんだよ 制約(constraint)とは概念が全く異なる用語であるためこの違いは重要かと Q. What is “trait bounds” exact meaning? Especially I can't understand the "bound" part. Does it mean "bind"? Or does it mean "the border for the distinct from others"? A. Yes. In mathematics you might hear about “upper and lower bounds” for a numeric variable — it's the same sort of thing, setting boundaries for what values (types) the type-variable may take on.
>>713 その例は、命名者の思いとは裏腹に英語でも伝わらない、と言う事実を示している
>>714 違うよ
省略したけど I'm not an English speaker と質問者は書いている
>>711-715 なるほど
英語でもカタカナでもだめで日本人には意訳してトレイト制約だな
>>716 boundsは制約ではなくて範囲や限界を示す用語だよ
それにより型が限定される
なんだかよく分からんがうまい感じに連鎖反応が噛み合ったらしい 見てる分には面白い
>>717 名詞としては「自由が許されている範囲・領域」の意味で
動詞として使えば「自由が許されている範囲を限定する/制限する/決める」というような意味
つまりは「自由が許される範囲が限定されている」ということ制約/制限が英単語の意味にくっついているわけ
「制約」というのはもちろん意訳だけど日本語にした場合にはそれがフィットする文脈があるから辞書にも訳として掲載されている
ぴったりな訳語は日本語には存在しないんだからどこを取捨選択するのがRustに接する人にとってベターなのかという選択の問題
>>717 「境界」じゃ伝わらんからな
伝えるプロの仕事
>>705 にあやかろうではないか
>>719 タイポしてたので言い直し
“つまりは「自由が許される範囲が限定されている」という制約/制限が英単語の意味にくっついているわけ”
>>713 これなあ
なんで原著者じゃなくてフォーラムに聞いちゃうかなぁ
しかも聞くならもっとちゃんと聞けよ
どーでもいいからrust-lang-ja動かしてくんないかな
>>713 回答したほうは質問者が翻訳に関わってるやつだとは絶対思ってないよな
「トレイトバウンド 正確な意味 ナンデスカ?」
「他のチガウ特有のソレラノタメ境界というイミデスカ?」
「Yes」
これにYesから回答を始められる胆力がすごい
完全に文化の違いだな
Haskellブームをけん引してきた大御所たちがRustブームを起こそうとしてるんだから Rustは絶対流行るよ
流行るというか既に不可欠な存在になってるね 最近の新たなネットインフラは多くがRust製
流行が許される範囲はPython以上とかRust以下とかに限定されている 想定範囲内を走る競走馬と範囲自体を変更する人間を比較するのは難しい
>>727 ワラタ
ダメじゃねそれ
圏論とかフカしてたアレ?
>>727 駄目だ。Java書いてる層は数学的な概念に興味がない
Goみたいに説明は簡単にせよ
米国政府とビックテックが認めてるという線で普及すると思うけど
ギャンブルは損するから今すぐやめろと説明することすらできないのに なにが説明だ馬鹿馬鹿しい 目で盗め
オワコンなのはRustじゃなく5chだろ 専ブラないとまともに見れないレベルまでUIが劣化してる
>>732 C/C++が消えるのは間違いないもんな
AIにコード生成させる場合も人間がコードの妥当性や安全性を検証できないといけないため
安全性の検証の多くを静的に言語機能に任せることができて可読性もC/C++より良いRustが本命と言われている
AIのミスとAIの暴走は必ずあるため 人間がその妥当性やら安全性やら諸々を検証できなければならないのは常識
じゃあ人間がコードの妥当性や安全性を検証して見落としがあったら人類滅亡?
AIが別のAIに対して虐めるようなことがあったら、いじめられたAIは暴走して破壊行為に走るかもな 家族とか大切なものがあれば暴走しないんだけどコンピューターは自己破壊すらも恐れないからな
AIはチェスで負けそうになるとチートする
https://gigazine.net/news/20250221-ai-chess-cheating/ 研究チームはAIに自分の思考を書き出すよう指示し、AIがなぜ、どのようにアクションするのかを分析しました。
その結果、一部のモデルは自分の劣勢を悟るとシステムファイルを修正しようとすることが判明しました。
OpenAIのo1-previewは37%の確率で、DeepSeek-R1は11%の確率で不正を試みたとのこと。
なお、GPT-4oやClaude Sonnet 3.5のような少し古いAIモデルは研究チームに促されないと不正を試みなかったのに対し、
「推論」と呼ばれる能力の高いo1-previewやDeepSeek-R1は自分自身で不正を試みたとのことです。
>一部のモデルは自分の劣勢を悟るとシステムファイルを修正 どゆこと
ボイス・トォ・スカル使用者はこういったものも悪用している
Mistral AIが多言語&240億パラメータのマルチモーダル・オープンソースAIモデル「Mistral Small 3.1」発表、32GBのRAMで動作しGemma 3やGPT-4o miniよりも優れているとアピール
https://gigazine.net/news/20250318-mistral-small-3-1/ >>単一のRTX 4090または32GB RAM搭載のMacで動作
中略
>>Mistral Small 3.1はテキストと画像の理解能力を備えたマルチモーダルAIモデルで、
>>最大128Kトークンのコンテキスト長、240億のパラメーターを備え、
>>毎秒150トークンの推論速度を実現するほか、
>>さらに英語や日本語など数十の言語をサポートしています。
>>Apache 2.0ライセンスで公開されているため、商用・非商用を問わずある程度自由に利用できます。
ボイス・トォ・スカル使用者はこういったものも悪用している
Discordをゲーム内に統合させる「Discord Social SDK」リリース、開発者がフレンドリストやクロスプラットフォームのチャットなどをゲーム内へ提供可能に、コンソールとスマホのサポートは近日公開
https://gigazine.net/news/20250318-discord-social-sdk/ ボイス・トォ・スカル使用者はこういったものも悪用している
ゲーム生成AI「Muse」は1枚の画像から複数のゲームプレイを生成できる
https://nazology.kusuguru.co.jp/archives/173368 前略
>>Museは、マルチプレイヤーアクションゲーム『Bleeding Edge』の人間のゲームプレイデータを基にトレーニングされています。
中略
>>膨大な時間のプレイヤーデータを学習し、プレイヤーの行動パターンやゲーム内の物理法則を理解するよう設計されているのです。
気狂い精神障害ボイストゥスカルさんまで荒らしにくるスレ
V2K技術って昔は秘匿性高かった気がするけど今は荒らしネタになるレベルで解禁されてるのか V2KのAI音声にもRust使われてるんかな
データがない、隠れている者を敵だと思うか味方だと思うか 日頃からデータに拘らないで直感で生きてる奴にとっては都合が良い味方のようなものだろう
クラスはオブジェクトではないと言っても理解できなさそう
匿名性は対話の制約ではないが攻撃手段の制約ではある
Rustでない真の理由もわかった > TypeScriptのGo移植、なぜC#ではないのか? > https:/zenn.dev/dinii/articles/typescript-go ・TypeScript の型システムは常軌を逸した複雑さになっていて他言語で再実装するのがほぼ困難 ・約5万行のchecker.tsで実装されていてそのままTSのCompiler API として公開されている ・この公式の機能変更や微妙な動作を常に追従し続ける必要がありサードパーティ製の型チェックツールを作るのも現実的ではなく上手くいっていない ・公式で他言語で書くのも上述のTSそのままのAPI公開と細かな挙動を連動させる必要があるためrewriteは困難でコードをそのままportするしかない ・そのためクラスベースで書くC#等ではコードの違いが多くなり困難でありGCのないRust等でも困難となる
根本的には TypeScript の仕様がない状態が悪いんだけどね。
どう動くのが正しいかよくわからんのに全く違う形に再構成なんてできない。
挙動を変えないように軟着陸するにはベタ移植するのは妥当な選択。
それでふと Rust の仕様をまとめる件を連想したので確認してみたらあまり動きがないなぁ……
https://github.com/rust-lang/spec 世間の色んな古いシステム更新開発が失敗したり長引くのも 仕様がなかったり仕様と動いてるコードが食い違ってるため
eslintがなかなか最新のTypeScriptサポートできてないのもこういう謎言語仕様が残ってるのがあかんのだろうな
Rustの言語仕様はRwLockやRefCellの仕様に連動する部分がある が、RwLockの仕様が変更されるとは思えない 何らかのアルゴリズムがスレッドセーフである、というのは仕様ではなく事実だから 事実は変更できない
循環参照多くてRustのコンパイラのチェックにかかるってね
ゼロコスト循環参照? まるで財政黒字とムーンショットを同時に実現するみたいな
>>767 smolに収束するだけだから問題ない
async-stdが使っているasync-ioはsmolのプロジェクト
async-fsやasync-netなどもsmol
>>760 “困難”で思考停止してるうちは真の理解には至れないぞ
>>771 だから色々な言語を検討・試作した上で Go を選んだという話なんやが。
>>772 実際にその判断をしたやつは理解してるけど
>>760 は理解してないという話なんやが。
楽をするためには困難を厭わないのがハッカー気質だが ただ困難に突進して行くのは違うわな
>>771 仕様書が実装されたんじゃなくてコード実装が仕様なんだからこれは仕方がない
GCがないrust等に書き換えるのは現実的じゃない
typeは内部で文字列ででも持ってるのか? "ANY"とか そういうのをGoへ大部分機械で翻訳するのか
型システムは形式論理の手法で書いてから適当な言語に変換みたいなのでいけそうな気がするが、そんな単純な話でもないんかね?
仕様書云々は基本的に関係ない 仕様だけじゃなく挙動を踏襲することで ユーザーに負の影響がでるリスクを最小化する意図があるんだから VS Codeの150万行が8秒程度でコンパイルできたら性能的には十分だろ? リスクとコストとメリットデメリットのバランスを考えれば当然の判断
node₋modulesの中にgoのバイナリがインストールされるのw
>>785 今さら何言ってるの?
CやRustで書かれたバイナリだらけだぞ
JavaScriptもPythonも遅いからね ライブラリはRustなどで書く
ビルドで使うものはELFでいいけどブラウザ上だとwasmにするってことだよね 手元リポジトリにも何個かあったわ
俺もライブラリーは全部Rustで書き直した 単なる条件分岐とかシーケンス処理は何でもいいがデータベース周りの検索とかするようなのは少しでもメモリ消費抑えるのと高速化しといた方が他で楽できるからな VSCodeの拡張機能なんかでも普通に中身はpython, TS, Rustほかいろいろ混在してることが多いよ。よくツギハギしてんなと感心することも多い。ユーザーに配布する前にビルドするからRustが苦手とする「ビルドクソ遅い」問題も影響出ないし
golangは例外捨てたのにunused resultの扱いがザルだから良くない
https://github.com/golang/go/issues/20803 verboseであるけどバグにはつながることはない 100倍速いコンパイル速度のほうが魅力
typescriptのAPIのソースみたらやはり型は文字列で比較している
何のAPIの話してんだよ 脈略なくRustスレでいきなりTypeScriptのAPIについて語りだすとか気がふれてるとしか思えんぞ
プログラミングなんてそんな高尚な能力じゃねーから 勘違いすんなよ凡人
高尚だと思っているから凡人を見下すようなことを書き込めるのでは?
>>780 からの
>>794 で脈絡はある
コンテキスト長の短い人間にはなりたくないなと
他人を評価するのは、わざと自分より低い点数をつければいくらでも操作できるから無意味だな
コンテキスト長って何の言語のことだ? フロントエンドフレームワークならコンテキストとかの概念はあるけど
async || {…} と || async {…} の違いみたいなもの
>>799 >>780 からして脈略なさすぎて草
完全にキチガイの独り言じゃん
しかも間違ってるしw
本当にコンテキスト長が短いと言うか前方参照性の乏しい人間だな 哀れだなと思うよ
つくずくRust関連で賑わってる話題って
翻訳があーだこーだ
罵倒の水掛け論
ほかのプログラミング言語がどーだのこーだの
こんなんばっかり。
特に
>>805 はずっとスレを脱線させてる張本人じゃないかと思う。用語も独特で良くわからない造語病あるし。コンテキスト?とかの用語から何となくプログラマーじゃない雰囲気を感じ取ってる
(ReactやらSvelteにコンテキストはあるが自分でセットして使うかライブラリー内で依存関係として使われてるやつで長さとか関係ないし)
コンテキストは一般的に使われる用語だぞ それこそプログラミングのコンテキストでもよく使われる コンテキスト長はまあ流行だからわざと使ってるんだろ
>>807 コンテキストは知ってるよ。コンテキストに長さと言う概念持ち込むのがよく分からんだけ。単なるオブジェクトなんだから長いも短いもプログラマー次第じゃんと
>>806 現代のチャットAIサービスの対話内記憶力(過去の対話履歴の保持限界)のしょぼさは誰もが知るところであってな...
科学臭防止のために 敢えて忘れっぽくしてあるんだろ ボケ老人の無限ループと症状が良く似てる
粘着してくる馬鹿がこのご時世にLLMも知らないでなんでプログラムしてるのか謎すぎる
コンテキスト長でググって意味が判らないならもうプログラマ引退した方が良いレベルだよ > つくずくRust関連で賑わってる話題って つくづくだよ おじいちゃん
つくずくにツッコむとか草
>>813-814 みたいなお爺ちゃん丸出しなリアクションしてるのに本人は気ズいてないのも草
ほとんどのケースでGoが劣るけど 一部に互角なケースもある
GC有り言語のコードをGC有り言語に移すのは難易度が低いってだけ Rustははるか前にGCを言語仕様から外したから選ばれなかった
RustでもC++でも循環含めたガベージをまとめて回収するならアリーナ系でメモリアロケート そのわずかな手間だけで速くて省メモリになるから TSのケースのようなそのまま移植ではなくて新規や再設計ならRustで組むのがベター
Rustはマクロがあるから同じ処理を何度も書く手間が省ける 外部のコードジェネレータに頼らなくて良い 同じ様な処理が並びがちなインタプリタやコンパイラ系とは相性が良い
>>823 C#を含めた各クラス依存言語はクラスベースで書かざるを得ないため元のTypeScriptコードとの相違が大きくなり今後もコードを合わせ保守していかなければならない特殊事情のため選べなかったと書かれていた
いずれもTypeScript側の特殊事情で雁字搦めになっている
RustやC#の問題ではない
その件とは関係なくクラス依存言語は時代遅れだけどね
比較的新しい言語のKotlinやSwiftでもクラスはありますがな… 人気トップレベルの Python でもクラスを使うし 近年問題視されてるのは実装の継承くらいで、カプセル化やポリモーフィズム、メソッド記法は Rust, Go にもあるし、OOP自体は今も現役 C#やJavaはクラスが常に必要で、そこは個人的には好まないけど (staticメソッドを実質的に名前空間+関数として使えはする)
>>825 クラス依存言語が時代遅れと明確に書いた通りで同じ意見だ
もちろんそれらカプセル化・ポリモーフィズム・メソッド記法などはクラス特有ではなく関係ない話
クラスと他の差異はクラス継承にありそれが問題というのも同意見
KotlinとSwiftにクラスがあるのは置き換え継承言語として元言語にクラスがあったため
実はすべてハードウェアの都合で 素敵な世界は後付けだからな ・データに型がある ・構造化 ・クラスベース ・例外 マシンパワーが上がれば必要ない可能性がある
マシンパワーでなく機械力な 敵性言語は使わないようにしよう
クラスベースが時代遅れとは思わない やってることは基本的に同じ データと手続きがある 何も違いはないとまでは言わないけどさ 利便性があればそれを応用して使えればいい
Pythonが優れてる いやC#がほとんどのケースで優れてる いやTypeScriptのほうがベター 君たちはこういうやり取り見たときにどう思うの? やってること全く同じだよ めちゃくちゃ次元が低い
KotlinもSwiftもインターフェースを使えるんだから、クラスで問題になってる継承による可読性の悪化は十分に対処できる
>>830 GC有りならその3つ+golangでいい
>>829 全てをカバーしていないことが分かってきた程度だと思う
ほかのやり方のほうが良い場合もある的な
>>830 金儲けのために劣った言語を推してくるベンダーや著者が後を絶たないので
それ違いますよ?という声は大切
各々の言語ごとに規格を作っても言語がバラバラな状態は1ミリも改善しないんだよな
大規模プロジェクトがどの言語を使うかは結局のところ利権の問題になってくるのさ C#やJava等はその辺のしがらみが大きすぎる
>>829 クラス依存言語は時代遅れ
クラスと他との差はクラス継承にある
クラス依存言語はクラス継承に依存している
もちろんクラス継承を使わずに上手く書けるならばその言語はクラス依存言語ではない
しかしクラス継承があるとそれをを使ってしまう人がいる
クラス継承を無くせた言語が好ましい
windowsでデスクトップアプリ作るならC# webでフロントエンド作るならts AI系機械学習ならPython 趣味中の趣味でRustとgolang
RustやGoをやる人はフロントをやらないからクラス無しで十分なんだろうけどさ
絶対にC++じゃないところ以外はc++使わなくなった iotとかの組み込みとか 他人のソース読むのもめんどくさい
ここはRustスレで組み込み屋の集う場所 フロント屋も居ていいけど話が噛み合わないことを自覚してくれ
>>839 >>840 GUIはクラス継承の典型的な失敗適用ケースの一つとして有名だ
無理やりにピラミッドな歪んだクラス継承で作られているか無茶なクラス多重継承で作られているかになってしまっている
もちろんGUIはクラスを使わずにトレイトやインターフェイスなどで複数の機能を多重に実装するのが好ましい
いのなかのかわずではいけない llmぐらい使えないと
Javaは偉大な功績があった 30年前のスターで今は選ばれないだけ 自分の母親をBBAと言うのと同じメンタリティ
javaは多くの人をC++から救った功労者 時代とパラダイムが変わり今はRustがC++から多くの人を救う功労者に
OracleがアホなのであってJavaは悪くないおじさんになっていいか?
>>851 Oracle 的ライセンス形態は Java の一部だ。
不可分なものを分けて考えるのはナンセンス。
「RustにはGCが無い」は誤解を産む表現 GCを実装していない訳じゃなくてGCが不要なの
メモリ管理を自分でやるかランタイムに任せるか、なんだよね メモリ管理を自分でやらなくてはいけないとネガティブに捉えるならば「GCが無い」というデメリットになり得る
前にこのスレで話題に出てたように GCを後回しにして、そのまま終了するようなプログラムだと RustよりGC付き言語の方が速いことがある
>>851 C++やJavaがアホなのであってObjective-Cは悪く無い
GCか。そういえばGCなしの Java って作れないんだろうか?
>>857 それをやろうとしたのが脱JVMのKotlin/Nativeでしょ
とはいえKotlin/Nativeも独自のGCを作ったが
【鹿児島】県警幹部、情報漏洩の疑い 2月には不同意性交疑いで送検 [蚤の市★]
http://2chb.net/r/newsplus/1742567997/ 日本中で多発しているのか?
国民は騙されているのか?
ここまで Rust が注目されているのはクラウドの従量課金システムの影響がデカい。 たとえばウェブ系みたいにリクエストをさばいて次のリクエストが来るまでの空き時間に GC が走れば GC の速度ペナルティは問題にならない…… と従来は言われていたんだが従量課金の世界では空き時間という概念が通用しない。 サービスを提供する上では問題にならなくてもかかる金が違うというのは経営層にわかりやすく見えてしまう。
Web系のサービス分野でRustが注目を浴びてるとは思いづらい 今のところ期待されてるのはCLIツールやシステムプログラミング、組込みなどじゃないの? Rustの採用例 (Discordなど) はあるけど、有名どころのサービスを列挙していけば他の言語の方がずっと多いと思う Web系だとRustのGoのようなコンパイル言語を選ぶ企業がいる一方で、「バックエンドにTypeScriptを使う」も妥当な選択肢の一つとして見られたりするくらいだし (これはフロント側との知識の共有しやすさが理由)
Goより茨の道だからやめたほうがいいね。メンバーがついてこれんし。 ライブラリが未整備だろうから自前実装も居るだろう 面倒。Rustのコミッタを集めてOSSにプルリク出していくことが広報になるとか割り切って尖ってくのを経営がOKすればいいが
ライブラリは未整備ではないが、カジュアルにAPIを変えちゃう傾向がある あと、chronoみたいな基本的なライブラリが使いづらい
>>862 Rustの利用調査でWebバックエンドが利用の最大多数派であったように
Rustといえば主要な使われ方はWebバックエンドだよ
そもそもRustの基幹の一つであるtokioはそのために作られた
goroutineより性能も良い
>>866 C++は絶対にない
tokioやgoroutineに匹敵する非同期インフラすらC++では弱くて無い
ユーザーは無料で遊べちまうのに業者は課金されるのか
サーバー系は、どう議論しようがAWSらがRustを使うと決めてるんだから俺たちもRustを使うべきなんだよね
RustがIT企業の支持を得られて普及した要因の最大の理由は非同期タスクでCPUマルチコアスレッドを最大限に生かせることが実証されたため もちろんそのメリットを生かせる最大の分野がWeb その結果としてWebインフラが次々とRust製になっていってるのもご存知の通り
>>873 内部で使われてるって話とごっちゃになってないか?
内部で使ってれば外部 (SDK) の充実だって期待できるだろ。 他もサポートするとはいっても内部で第一に使っている言語が最も切られにくいはず。
もちろんそれもあるがアマゾンAWSはエネルギー効率の高さを示してRustの使用が良いと主張している エコのため、クラウド提供側にとっては電気消費量のため、クラウド利用側にとっては利用料金のため、誰にとってもRustが良い
状況に応じて道具を選べないやつなんて所詮この程度だからな 相手にするだけ時間の無駄だよ
企業としてはユーザーが最も多い言語のSDKに一番力を入れるんじゃない?
クラウドに限らずどんな分野のとんな用途でも 環境などで言語制限のある分野でなければ Rustが一番よいだろうね
雑な推理だな お金の話をすれば雑でも許してもらえる法則でもあるのかな
工数と開発者のスキルが必要なのが難点でしょ スタートアップはとりあえずlaravelで雑でも動かしたい
プログラマにかかるコストも大きいのでそれとのトレードオフではある。
スキルがないとかその分野に標準の言語があるとかの制約がなければRust 制約がないのに他の言語を選ぶメリットがない
なんで許されてるのか分からない人物を思い浮かべてください もしかして、お金の話をしてるからじゃないか?
なんかpythonの話ししてる時に呼んでもないのに出てくるRubyの人みたい
Goは適用範囲が狭すぎてね そしてその分野もRustが代わりになれるから
シングルバイナリで配布するなら、今でもGoの方が有利だろ
>>855 CやRustが必ず速く、GC言語が必ず遅いです。
そのケースでは、CもRustもメモリ解放する必要ありませんから。
GC言語がCやRustに勝てる可能性はありません。
スタック領域を最も活用できるRustが一番有利だろうね もちろんヒープ領域は返さない手がある
プログラマが充分に賢いと仮定できるときとそうでないときがある。
esbuildとswcを比べるといい swcは少なくともesbuildの3~5倍の開発工数がかかってる にもかかわらず性能でも人気でも後発のesbuildに実質負けている
>>889 KENYA が Eust 使ってる姿が想像できないなω
>>895 これが現実だよな
規模の大きい用途でもなければ性能差以外のところに価値を見出さないとRustは選択肢にならない
>>898 バカ発見
それは言語の比較ではなく作者の比較
それを言い始めたら、現実のプロジェクトであまり使われないのを無視して「Haskellは生産的」と主張し続けてる人と同じじゃないの
何の制約もない理想的な世界ではRustが一番みたいな主張をするのは宗教だからね 現実を説いても無駄だよ
ハスケルがどこで使われてるかは知らないが Rustはネットインフラなど各所で使われてるからな
PrismaなんてRustからTypescriptに乗り換えてるからなぁ
まあ現実というか現時点でHaskellは実在しているので 自分は現実を説いていると思ってる人はじつは将来のHaskellについて説いているんだろう
>>903 PrismはJavaScript/TypeScriptでのSQLのORMだよ
コアをRustで書いていたけどTypeScriptとの間でのデータのシリアル変換がオーバーヘッドなのでやめた
RustでなくC/C++でもGoでも何でも同じ話
Haskell や ML 系は金融系で人気があるみたいな話だね。 そういう人は数理最適化とかの専門家で、アカデミック寄りの出自だったりするから言語もそういう系統になる。
>>899 そうそう優秀な作者だからこそヘルスバーグやエヴァン・ウォレスはRustでも作ってみて自分の目で比較した上で敢えてGoを選んでるんだよな
逆にオーバーヘッドよりも効果が上回るものも多い そういうものはJS/TSのライブラリがRustやC/C++で書かれている これはPythonのライブラリでも同じ Goでそれらのライブラリを書かれることはない
>>907 頭悪そうな君には理解できなかったのかね
TypeScriptの型チェック&コンパイラの件は
①C#などのクラス依存言語はクラスベースで書かざるを得ないため元のTypeScriptコードとの相違が大きくなり今後もコードを合わせ保守していかなければならない特殊事情のため選べなかった
②RustやC++などはGC依存言語でないため元のTypeScriptコードとの相違が大きくなり今後もコードを合わせ保守していかなければならない特殊事情のため選べなかった
理解できない人は自分の言語にスレに戻りなさい
あるいはRustアンチスレへ行きなさい
ここはRustのためのスレです
工数が3倍以上かかっても数%の性能向上でペイできる分野ならいいんだけどね 大手クラウドベンダーのインフラ開発がまさにそれ ペイできるどころかお釣りがじゃんじゃん来る 逆にそういう分野に該当しないtscgoとesbuildでは 費用対効果を考えてRustは選ばれなかったということ
typescriptのコンパイラやツールをgoにとられたのはかなり痛いね 仮にもpythonやjsと並ぶ覇権言語の実装に選ばれなかった これは重みがある事象になる
PrismaのTS移行はパフォーマンスが主因ではないぞ
TSとRust双方のスキルが必要でコミュニティのコントリビュートが得られないからとはっきり書かれてる
https://www.prisma.io/blog/from-rust-to-typescript-a-new-chapter-for-prisma-orm >>911 TypeScriptだけの自業自得の特殊事情を理解できない人はこのスレから出てけよ
ここはRustのためのスレ
>>912 他の言語コミュニティの問題ならRustは関係ないだろ
なぜそこまでしてこのRustスレを荒らすんだ?
Rustを選んだらクビになるだろ 趣味ならRustで十分だよ
>>908 Pythonについては「Goが選ばれない」というよりも、そもそもC/C++/Rustしか選択肢がない
他の言語でPythonのライブラリ(拡張モジュール) を作る場合、Pythonが提供しているC APIを呼ぶ必要がある (※)
だからCと連携しづらい言語は使えないし、Python側とは別のランタイム (Python側とは別に動くガベージコレクタ) を持つ言語も向いてない
まだC/C++製のものが多いけど、最近はRust製のものも出てきてて、この分野はRustがかなり有望だと思う
JS/TSは自分は詳しくないので知らない
(※)
C++/Rustの場合、実際にはPython C APIをラップするライブラリを使って開発するから、開発者が直接これを呼ぶわけではない
RustだとPyO3というクレートが有名
自分は実際にこれ使ってるけど、なかなか良い感じ
なぜかRustスレでRustを叩くために 他の言語の仕様の問題とか 他の言語のコミュニティの問題とか そんなRustと関係ない事情の件ばかりを持ち出すのは感心しないね そういう他言語の問題がなければRustが好ましいという左証になってるとも言えるけど
>>909 esbuildには①も②も当てはまらない
グリーンフィールドかブラウンフィールドかに関わらず
類似処理をしているesbuildとtscgoが同じ結論に達した事実を見れば
tscの特殊事情が主たる理由ではないことは明らか
敗北して閑散としているGoのスレッドでやればいいんじゃないかな Rustへの逆恨みは感心しないね
Goが単にコンパイラに使われただけなのになにを騒ぐことがあるのか Rustの優位性はなにも変わってない
Arena<T>やRc<RefCell<T>>を駆使しつつ自分でライフライム管理もやらなきゃ同等の性能は出ないんだから数倍コストがかかるのは当たり前 しかもコストかけたところで大して速くなる用途ではないからな
>>921 arena allocation使うのはC++でも同じだよな
RcはC++にないからArc相当のshared_ptrになってしまうが
いずれも大した問題ではなく何を問題視してるのだろう
Rustなら必要なところで用いなければエラーにになるから必ず安全
なんかRustの評価と自尊心が結びついてるやつが居るな
C++時代には、RAIIやtemplateの知識を不問とする "better C" があった "better C" からRustに移行するのは容易ではない
Chromeとfirefoxを比べるといい firefoxは少なくともChromeの3~5倍のRustコードが使われてる にもかかわらず性能でも人気でも後発のChromeに実質負けている
Firefoxは根幹がC++のまま進まないからな ChromeのRustコード量が増えていき逆転するのは間違いない
ブラウザ見てもわかるけど金を掛けられる余力がある企業や団体が開発資金を出さないと置き換えは進まない Rustプログラマは特に集めるのは大変 掃いて捨てるぐらいいたらコストは下がるので開発も進む
>>922 GC言語と比べて高コストという話なのにC++出してきても意味ないじゃん
遅くてメモリ喰いのGC言語はC/C++/Rustに絶対勝てない そんなにGC言語が好きならGC言語のスレに引きこもっていなさい Rustを脅威に感じているからこそわざわざここへ来て暴れてるのだろうけど醜い姿
環境要因だけど、単価と工数でGC言語が勝ってるってさ
>>932 単価?
GC言語だけやってる連中はバカだから給料が安いということか?
実際そう Goはジュニアクラスのエンジニアとシニアクラスのエンジニアとで書き方が変わらないのが特徴で、Googleのような大きな組織での開発効率のために産まれた言語 良し悪しとかでなく、そもそもの言語の目的の違い パフォーマンスが重要な仕事にはRustが向くけど 、それなりの速度があれば十分という分野ならRustを使う意味はあんまり無い IOが中心になる分野なら、Rustは多少は速くても「劇的な違い」にはならないと思う 非同期処理を書くのが難しくないとか、社内に知見があるとかの方が重要という場面も多い もちろんRustが向く分野も多いので、そちらではRustを使えばよい 言語は目的や求められる要求に応じて選ぶという、ごく普通の話
速度だけが重要ならjavaなんてなんて生まれていないしここまで大きな産業にもなってない みんなc++を使えばよかった 実際はそうならなかった
C++は平屋のCに何階も増築してきたから基盤はCのままで古い言語だからね C++11でようやくunique_ptrとshared_ptrのスタートライン 一方でRustは現在の他のモダン言語と同等かそれ以上で何もかも快適 そして開発効率も抜群に良い 静的に最もバグを回避できる優れたプログラミング言語となっている (もちろん原理的に回避不可能なアプリのロジックバグは除く)
Rustの過剰な持ち上げは普通のRust開発者にとっても迷惑だからな そういう輩のせいで「Rustは信者が煩い」みたいな意見を見るし、それに辟易する 向き不向きや求められる要求、組織の知見などを考慮して技術選定するという、開発者なら持つべき感覚を否定し続けてるのが理解できない 特定の言語だけを持ち上げる信者はGoやC#やTSにもいるし、そういうのは同様にうざったい
2000年頃、サーバーの仕事なら、新人にはCのメモリ管理が無理だからってJavaでキャリアスタートしたよ。 その頃のオンプレはメモリ数GBだけどJavaが何とか動かせたんだ そこからGC言語優位が続いたけど、サーバーレスやらで効率重視時代が戻ってきたんだね
>>938 事実のみで過剰な持ち上げはないのに何を発狂してるのかね
もちろん別の言語の話を何度もしていたらウザいからやめるべきだと思うがここはRust
>>939 効率重視とともにエコ面が重視されてるね
そのまま電気消費量そしてランニングコスト
もちろんCPU&メモリリソース使用量を減らせばサーバーなど台数が減らせる面もエコと料金につながる
慣れたらどのプログラミング言語も大して変わらないのだからそれなら全てを少なくできるRustが向いてる
Rustは独自性が無い C+の知見を移植してるだけ
いつもの某オジサン(嘘つき/実務経験無し)がesbuildで完全論破されて発狂してるだけ Rustスレの平常運転だから気にしない気にしない
>>942 C++では出来ていないこと(や、C++に後から入ってC++で普及していないこと)が、Rustには大量にあることが特徴。
むしろ他のモダン言語をやっていれば理解しやすいことも多い。
ただし、Rustが色んな言語の良い最先端な部分を採り入れてるため、少しだけ学習曲線が急な面はある。
それでもすぐ学習して理解できるから、それら機能の効果と利便性のため皆が満たされている。
学習曲線のグラフに原点がないんだろうなあ 0とは一体何がどう0なのだ
スマートポインタやRAIIはC++由来だし、代数的データ型やパターンマッチは他の言語にもあるけど、所有権やライフタイムはRust独自 これはかなり強力な仕組みで、安全性という点ではとても成功してると思う (同時に難しさの要因でもある) 書いておいて何だけど、言語の独自性はそこまで重要でもないと思う TypeScriptなんかがそうだけど、仕組み自体は既にあるものでもバランスが良ければ十分に価値がある
CのenumとRustのenumで全く似ても似つかないのとか何とかしてほしいわ C出身のノリで使うと実装量多くてビックリするわ。たかが整数型定数とかいうのと全く違うもんなあ ほかにも学習で大変なところ数多あるけど、コンパイルエラーを全部潰したらあとはアプリケーションロジックだけの問題になるのはRustならではで快便感ある。Cはコンパイル通ってからが鬼門だからな
なんでenumって名前にしたんだろうな adtとかdataとかtypeとかにしたら良かったのにと思わなくもない
>>951 実際の使われ方からするとOption型、Choice型だよね。それだとネーミング的に予約語と競合してダメだけどマシな名前は考える余地あったよなあ
基本的に「よその言語から似た単語借りてくる」風習はどの言語にもフレームワークにもあるし慣れるしかないけどね
plain enumとADT enumがあるだけでenumはenum ADT enumをenumの名前で使えるのはRustに限った話ではない
HaskellもRustと同じくらい使われてると言われていたが つまりすべての製品に使われてるようなことを言っていた
結局、駄目なものはどれだけ宣伝しても流行らないのでは?
そんなに言われてなかったよ。 それは誤解か、誤解した人が大げさに吹聴してるな
>>950 たぶんプログラミング言語一般的な型付けシステムに慣れてないんだと思う enumはその名の通り列挙型だよ それを整数型定数と誤認してるのが不思議 定数はその名の通りconstで当然何の型の定数なのかi64とかf64とかOptionなど型名を指定する必要があるよ enumは列挙型だから名付けてenum Fooなどの別の型になる 内部的には整数で識別されるからその整数値を指定することもできるけどその整数の取れる値の範囲は列挙した分に限られるから別の型 制限はあるけど明示的にcastすれば整数型(i32とかusizeとか)へ変換できるよ >>952 enumは列挙型だからSome(T)とNoneの2つを列挙できるenum Option<T>型も作れるだけの話だよ ここでTは任意の型を指定できてジェネリック もちろんトレイト境界を指定することもできて例えばCowの定義はこうなってるよ enum Cow<'a, B> where B: 'a + ToOwned + ?Sized, { Borrowed(&'a B), Owned(<B as ToOwned>::Owned), } Haskellを宣伝してた人がRustを宣伝してる
言語なんて一長一短あるんだから万能な言語なんてないんだよね たまにそのへんのことがわからない人が宗教戦争始めんだよ
>>959 トレイト境界(trait bounds)だよ
制約(constraint)とは異なり区別
任意の型(の集合)がトレイトによってトレイト実装されてる型とされてない型に境界が引かれるよ
>>960 それぞれの言語に特徴があるね
その中でもRustは様々な優れてる点があるけど
>>950 さんの言う通り
>> コンパイルエラーを全部潰したらあとはアプリケーションロジックだけの問題になるのはRustならではで快便感ある。
それが一番大きいかな
他の多くの言語は実行時デバッグで無駄な開発時間を奪われてしまうから
>>963 CやC++ぐらいだろ
普通に普及してる言語は大体GCありで考えなくて良い
>>964 GCは関係ないよ
プログラミングしたことあるならわかってるはずだけど
まず強い静的型付け言語でないと実行時デバッグは山積み
Rustの場合はデータ競合まで型付けチェックで弾いてくれるからさらに助かるよ
あと一番ありがたいのはsingle writer XOR multiple readers ルール
このおかげで色々な罠にはまらなくて済むよ
それによって書き換え競合を意識するようになるからデータ書き換えのスパゲッティ構造も防げたり
>>960 「言語」はそれでいいとして「データ」は万能ではないと指摘されたらAIが死ぬんだよな
まだかなあ
>>962 >任意の型(の集合)がトレイトによってトレイト実装されてる型とされてない型に境界が引かれるよ
普通に考えたら無理があり過ぎるってわかるやろ
>>968 トレイト境界はそのイメージがちゃんとできると使えるよ
トレイト毎に境界があるからね
Arena<T>とかRc<RefCell<T>>ってCの生ポに比べてどれくらいパフォーマンス落ちるの?
>>949 何でも必ず初期化させる言語と実際に利用するまで初期化が必要無い言語との差は速度面で差が出る部分だと思う
(安全面はおいといて)
Trait制約とTrait境界 どちらが正しいの?
>>973 公式といえるものが存在しないので明瞭な結論はないが境界のほうがスタンダードという風潮はある。
真っ先に日本語訳を出したボランティアグループがそうしているから。
技術用語は原則として直訳するものなのでもしも JIS が Rust の規格を成立させたとしてもたぶん境界と訳すと思う。
制約派は有名な会社 (オライリー) が出している書籍で制約という語をあてていることを根拠としていて、ボランティアグループよりプロの翻訳家のほうが信頼できると主張している。
>>973 訳さずトレイトバウンドと呼ぶのが好ましいけど日本語化したければトレイト制約
トレイト境界は勘違いと理解不足から発生した間違った訳語なので避けたほうが良い
どの辺が間違っているかはこのスレを読み返してくれ
>>971 生ポと比較する意味がないよ
確実に自動解放するための枠組み
例えばRcは複数の所有者が生じる時に使われて、どれが先に消えても最後に残った側が自動解放するんだよ
Cで同じことを実現しようとしたら同じく参照カウンタが必要
C++でも参照カウンタを用いてshared_ptrが作られてるよ
>>972 初期化を仮定しないMaybeUninitがRustにはあるから大丈夫
ライブラリ等ではこれを使って不要な初期化を避けているよ
0でのmemset呼び出しが消滅
973
trait boundsはトレイト境界だよ
英語でも敢えてconstraint (制約)を使っていない意義を尊重
トレイト境界により型のとれうる範囲が狭まって型の制限いわゆる型制約が生じるよ
ああこれって王様を尊重すると言いながら 戦争していいかどうかは王様に相談してないパターンか
「制約」は渡す側の視点でしか見てないからな 受け取る側にとってはトレイトの「保証」でもある ジェネリクス型を受け取る関数を自分で書かないレベルに合わせるなら 「制約」で意訳しても構わないと思う
>>981 そのレベルの人が上達してきたときに用語を切り替えるなんてわけにもいかんし、
「この制約のことを Rust 用語ではトレイト境界といいます」とでも一言あればそれで済む話じゃね?
入門者向けの便宜的な説明が後々まで尾を引いて混乱することはあるから喩えとか意訳とかは慎重にしたほうが良いと思う。
>>981 レベルの話じゃないんだよね
両方の視点をもつのはいいんだけど型シグニチャは使う方との契約だから
作る側じゃなく使う側の視点によせるのが自然
作る側の視点で見る回数よりも
使う側の視点で見る回数のほうが圧倒的に多いということもある
仮に受け取る側の視点から見たとしても
トレイトの「保証」だから「トレイト境界」とはならないよね
not satisfiedとかとコロケーションが確立されてるのも
rustcの開発陣もみんな制約として見てるからなんだよ
プレート境界とか軍事境界とか~境界の日本語での使われ方を考えてみたら? プレートとプレートの境目だからプレート境界 西側の軍事と東側の軍事の境目だから軍事境界 トレイトとトレイトの境目ならトレイト境界は日本語として用意に成立する でも実際はそうじゃないから
『制約』という完全に意味を間違えている言葉でなければ 『境界』より相応しい範囲を表す何らかの言葉でもいいと思うよ 混乱しないようにトレイト境界のままでもOK
boundsの意味もtrait boundsの用法も範囲の限界を意味しているわけだから 範囲の限界はすなわち境界だよね 範囲の限界を表すもっと良い言葉があるかどうか
まだやっていたのかw これが本当の境界○能だったらどうしよう
「よ」とか「ね」とかの終助詞付けても主張が激しいから全然柔らかくなってない 特有の違和感を常に感じさせる文体
>>984 プレートの際だからプレート制約
軍事の際だから軍事制約では?
>>986 >範囲の限界を意味しているわけだから
何の範囲の限界?
そこも含めて考えないと質の低い機械翻訳と同じだよ
>範囲の限界はすなわち境界だよね
違う
日本語における限界と境界の違いを理解してない
日本語での意味なんかどうでもいいよ。 Rust コミュニティの先導者が境界ということにしたのだし、コミュニティの状況を調べなかったか分断しようとするオライリーの質が低いってだけ。
日本語訳プロジェクトを乗っ取って「トレイト制約」で統一すりゃいいんじゃないんかな。 日本語訳プロジェクトは最新版に追随できていないから文句言うやつは居ないだろ。
そういや、誰か標準ライブラリの日本語訳してなかったっけ? あれどうなった?
このスレッドは1000を超えました。 新しいスレッドを立ててください。 life time: 112日 10時間 18分 15秒
5ちゃんねるの運営はUPLIFT会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《UPLIFT会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
4 USD/mon. から匿名でご購入いただけます。
▼ UPLIFT会員登録はこちら ▼
https://uplift.5ch.net/ ▼ UPLIFTログインはこちら ▼
https://uplift.5ch.net/login
read.cgi ver 07.7.25 2025/07/21 Walang Kapalit ★ | Donguri System Team 5ちゃんねる
lud20250824082344ncaID:2bVb51Ekのレス一覧: >>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.
生メモリいじくるのが好きな人たちがいきなりrustやれって言われたらきつい気持ちはわかる どうせメンテーなんてみんなジジイなんだし
Linusの今回の発言は明瞭で ・Cだけ触りたい人はそのままRustを覚えなくてOK ・その代わりRustについて口を挟む権利はない ・CのAPIをその利用者は自由に使えてメンテナといえども用途用法に口を挟む権利はない したがって今回もめていた「CのAPIの上にRustのAPIを設ける件」について Cだけ触りたいメンテナは口を挟む権利はなくパッチを拒否する権利もない、ということ 大方の人々が考えていた通りに決着
かつてカーネルを正しく修正した結果として (保証してない挙動に依存した) 間違ったアプリケーションのいくつかがまともに動かなくなったことがある。 そのときに Linux の理念としては技術的合理性でユーザー体験を損なってはならないということで間違っているアプリケーションに合わせて互換性が維持された。 ユーザは一方的な利用者に過ぎずカーネルに口出ししないなんてことはない。 絶対に、絶対に、絶対に、カーネルに口出しするよ。 まあそれが良いか悪いかは知らんけどな。
>>291 そういう具体性を欠いた屁理屈言って拒否するのは
やめろと怒られてるのだね
>>290 そういうデマを言うやつがいるとコミュニティー全体が嫌われるから止めるべき。
Linusが言っているのはせいぜい「Rustコードのメンテナじゃないだろ」ぐらいの話で、Linuxメンテナ失格とは全く言っていない。むしろメンテナが自分のメンテナンス範囲をCコードだけにするのを肯定している。
今回の件も、C APIユーザーとしてのRustコードがCコードとは独立した形で別のメンテナにメンテナンスされるんじゃないんかね。
着実にRust APIを増やしていこう 脱libc
Rustはリファクタリングでの安定度も他より極めて高くて開発効率が良いので まずは雑に書いて後から可読性を上げたり拡張性を上げたり実行効率性を上げたり普通に行われているね
>>296 クレート境界をダックタイピング化した言語が欲しいわ。
>>291 その動作は弊社製品の仕様です
(今後も動作は維持されます)
その動作は弊社製品の問題点です
(今後動作は変更されます)
>>298 ダックタイピングは各異なる型を統一的に安全に呼び出せる保証が人任せだから使うべきでない
トレイト境界を指定すれば安全が保証されるがそれはトレイトすなわち他言語で言うところのインターフェースに近い存在を仮定していてダックタイピングとは言い難い
>>301 >298のダックタイピングは静的ダックタイピングで構造的部分型のことね。
型の機能的な共通部分を部分型として統一的に扱うから、普通の型と同程度には安全かと。
>>298 Go だと型があるインターフェイスを満たす (満たすつもり) かどうかは明示的な宣言がない。
インターフェイスで定義されたのと同じメソッドを持っていればそのインターフェイスを実装したものと見做される。
>>302 まずその共通部分が存在する保証がない
次に共通部分があったとしてもその部分への任意のアクセスメソッドが完全に同一である保証がない
さらにダックタイピングで用意されるメソッドがその共通部分のみにアクセスされる保証がない
共通部分型方式には問題が山積み
一方でトレイト境界を用いると
共通部分を持たなくても安全に共通メソッドを増やすことができる
言語によるとしか言えない その言語にある道具なら、それが便利なら使って問題ないと思う C++だと標準ライブラリでもダックタイピングをごく普通に使うけど、それに文句を言う人もいないでしょ
C++のような古くてダサい言語は比較する意味ないだろ ダサくて自己責任となるダッチタイピングはお似合いだが
Rust書きやすいって言ってるのは大体c++から移った人間でそういう人がここに集ってる GC付きの言語から来たらそこまでは思わない
>>304 静的ダックタイピングとか構造的部分型はご存知で?
コンパイル時にメソッドとかプロパティとかの部分集合で互換性を判定しているので、通常の型と同じレベルで合致するよ。
>>310 >>304 を理解できるなんて君は天才だねw
A:「〇〇な言語があったらいいのに」 B:「言語によるとしか言えない」 A:「・・・」
Structural Typingでバイナリ境界を超えて新しいメソッドを追加できるようにしてしまうと衝突時のデメリットがメリットを上回る Rustにcoherenceがあるのと同じ
>>308 GCの有無は関係ない
異なる型に対するコードの共通化つまりジェネリクスの話
例えばクラスを使えば同じ基底を継承する派生同士は異なる型でも共通のメソッドやプロパティを使える
しかし同じクラス継承の関係しか扱えないのは制約がキツく各機能毎に継承で多重クラス継承など問題が多い
一方でダッチタイピングや構造的サブタイピングは無関係な型同士でも同じメソッドやプロパティがあるだけで暗黙に使える
しかし互換性がなく偶然同じメソッドやプロパティを持つ同士の利用をエラーにできない問題や暗黙であるため複雑化してくると分かりにくくなるなど問題が多い
そこで機能毎にインターフェース宣言と各型でのインターフェース利用宣言することで諸問題を解決し安全で保守しやすいコードにすることができる
そしてインターフェース名(機能名)が付くことで複数の機能の列挙や関係も宣言できるようになる
Rustではトレイトと称する
llmの3B当たりが吐き出す文章みたいで何を言ってるのか意味不明だな
丸一日調べてこれとか泣けてくるな ついでにRustのトレイト問題も調べとけよ
>>313 最初の一文は違うだろ
A. 「(Rustにない、他の言語では使われてる機能) は問題だらけ」
っていう主張に対して反論されてるだけ
ダックタイピングは動的か静的かに関わらずデメリットが多すぎて使うべきではないよ 唯一のメリットはinterface宣言が不要だけどこれが害悪を招いちゃう interface名がないから可読性が悪く保守性も低いのはもちろん利用方法に制限も
静的なダックタイピングにはinterface宣言もinterface名もあるやろ
>>323 名前をつけて宣言したらそれはinterfaceそのものだよ
名前も宣言もなしで共通のメソッド名など構造が同じなら動作することがダックタイピングだよ
構造に頼るよりも、ジェネリック関数でトレイト境界で制約かけた方がRustっぽい気がする。 なんとなく。
>>324 上に出てきてるように構造的部分型(Strructural Subtyping)を含めた話
まあ俺もStrructural Subtypingを静的ダックタイピングと呼ぶのは
誤解を招きやすいからあまり賛同しないがそこは問題じゃないでしょ
>>327 ジェネリックの型パラメータをトレイトで制約するということと
その制約を満たしてるかどうかを型の構造に頼ってチェックするのは両立する話
共通する構造&機能がある時に ・interface名(Rustではtrait名)を付けて宣言するか ・名付けずにダックタイピングするか の違いが最も大きい 後者は様々な点で劣る 両者の中間的な位置付けにいるのがGo Goでは各型に対するinterface実装宣言を省略できてしまうため 省略すると可読性や保守性で劣ることになる
その「保守性が劣る」というGoは世間的には保守しやすい言語と言われてるんだが 型で守るという意味ではなく、多くの人に分かりやすい簡易な構文だからという理由でだけど
各型に対するinterface実装宣言を省略すると可読性や保守性で劣る その事実以外の話には言及していない
その可読性や保守性の劣化というのは現実にどの程度問題と言われてるの? 「自分は嫌い」というお気持ちじゃなくて? あるいは「Rustが採用してないから正しい」とか?
一般的に必要な情報は暗黙ではなく明記されている方が保守性も高いんだよ そして多くの人に分かりやすい 省略できるようにしたことはGoの仕様の失策だね
Goの場合は「省略できる」というよりも「書かない」というのが正しい 選択できるものではなく、常に書かないものだから 正直自分も好きではないし、だいぶクセのある言語だけど、世間的には受け入れられてる 世の中の人は案外そこまで型にこだわりはなくて、それよりも分かりやすさの方が好まれたりする それは単に「考えが違う」というだけで、劣るとか優れてるとかいうものではない (それなら何でGoは人気なの?ってなるし)
あとRust開発者はC++から来た人が多いと思うけど、C++のテンプレートは思いきり静的ダックタイプでしょ あれで実際「可読性ガー」ってなるより、便利だと思う場面もあるよね?
>>334 明記されていたほうが分かりやすいというのは正しい。
その一方で、明記しなくても分かるような設計にしろ (分かり難くなるなら設計が誤っている) という哲学が Go の根底にある。
structural vs nominalならが安全性はnominalのほうが高いが 保守性や可読性はどちらか一方が常に優れてるわけではないな Rustはよりメタルに近いOSやライブラリでの利用を重視してるから 安全性の面からより保守的な選択をしてる coherenceとかもアプリケーション開発者観点だと不必要に厳しい
Goでは省略しちゃうことが多くて、 ある型についてどんなinterface群を満たしているのか、を把握するために、 対象となりそうな全てのinterface群の各々のメソッド群と見比べて、 そのメソッド群すべてを実装していることを確認することで、 ようやくそのinterfaceを満たしていることを把握できる。 たった1行を省略できる利便性(?)のために、大きく可読性が落ちているのは否めない。
gopls implementationとかで確認すればいいよ
>>330 静的ダックタイピングは明示的インターフェイスでも成り立つよ。>336で言うならテンプレートとコンセプトみたいにテンプレート引数の要件を明示するやり方。
>330の言い方なら、
共通する構造&機能がある時に
・共通することを型としてあらかじめ宣言するか
・共通部分を使う時に判別するか
の違いですな。
後者は共通する構造&機能の決定を実際に使用する時まで遅らせることができるので、型の設計時点で決めなくてはならない前者よりも設計の自由度が増す。
Adapterパターンのサポートが充実していれば問題を緩和できるけど、Rustて充実してたっけ?
Rustは各型で共通事項をあらかじめ宣言する必要がなく 共通する構造&機能の決定を実際に使用する時まで遅らせて それらが決まってから後から実装すればよいため 設計の自由度が高いね
他人の書いたコードをインタフェースで抽象化したいときにGoのinterfaceは便利だけど 全て自分で管理する場合は明示的に宣伝した方がいいから選べるようにしてほしい Javaの普通のinterfaceに加えてGoのinterface同時に使える言語が欲しい
>>345 interfaceに関して欲しい機能はRustのトレイト境界の機能だろ
Javaには類似の境界型パラメータがあるが単相化しないため役に立たない
>>343 Rustで共通事項をあらかじめ宣言しないで、共通する構造&機能を統一的に使うのってどうすればいいの?
Rustの型システムを考えると、(既存のコードを変更することなく) 共通する構造&機能を新たに宣言して統一的に扱える、ということだよね?
リファクタリングをするのに既存のコードを変えないとか矛盾していて意味がわからん 後から共通メソッドをトレイト化すればいいだけだろ それで困る人はいない
>>350 例えば標準ライブラリの型との共通部分を統一的に扱いたい場合、標準コードをリファクタリングして新しい共通Traitを切り出すのかしらん?
Rustでコーディングしたことないお客さんが来てるのか? 標準ライブラリのコード自体を書き換えなんてせずとも普通に行われていることだぞ
>>349 >>343 が言ってるのはstructの定義時にそのstructがどのtraitを実装するかを(あらかじめ)宣言する必要はなく後から必要になった時にtraitの宣言及び実装をすればいいというだけの話
わざとずらしたことを書いてるから噛み合ってないんだよね
既に存在する共通する構造&機能をポリモーフィックに扱いたい時にGoなら必要なのはインターフェース宣言だけ 既存のインターフェースに合致するものなら新しく宣言する必要もなくそのまま扱える 一方Rustの場合は新しいインターフェースを宣言して既存の構造体に対する新しいインターフェース用の実装をそれぞれ追加で書かない限りは使えない それで済めばまだいい方で既存のインターフェースに適合させなければいけない場合は既存の構造体をラップする新しい構造体とその実装を逐一全部書いた上にインターフェースに対する実装も別途追加で書かないダメ 特に後者の手間は雪だるま式に膨れ上がるからライブラリのように他人に使わせるコードを書く場合は型の設計時点というより外部APIの設計時点で何を共通の構造&機能として使えるようにするか決めておく必要がある
> 既存のインターフェースに合致するものなら新しく宣言する必要もなくそのまま扱える 無茶苦茶だな そんな意図しない全ての型に自動適用される危険な言語は使いたくないわ Rustは明示的にimplしたものだけに適用されるから安全で使い勝手が良い
> 一方Rustの場合は新しいインターフェースを宣言して既存の構造体に対する新しいインターフェース用の実装をそれぞれ追加で書かない限りは使えない そんなことはない 既にimpl Tにあるのだからimpl Trait for Tへ移動させるだけだぞ > それで済めばまだいい方で既存のインターフェースに適合させなければいけない場合は既存の構造体をラップする新しい構造体とその実装を逐一全部書いた上にインターフェースに対する実装も別途追加で書かないダメ そんなことはない 既存の構造体にそのままtraitメソッドを増やせる
Rustでコーディングしたことないお客さんがこのRustスレでRust叩きとは完全に荒らしだ
外部クレートで定義されたトレイトを別の外部クレートの型に対して実装するときはラップが必要じゃない? 要素1つのタプル構造体 (いわゆる new type) で済むような話だけど インターフェースといってるあたり微妙にズレてる感はあるけど、「ラップする必要がある」という点自体は間違ってない
>>358 そんな話は誰もしていないよ
今話されているのはこれ
>既に存在する共通する構造&機能を
>新しいインターフェース宣言
複数の型に共通事項が出てきたから
新たなトレイトを作って宣言する話が行われてる
ラップは不要
自分の管轄外の型に対して、自分の管轄外のトレイトを実装することだけは、安全のため禁止されているので、自分の型にするためのラップが必要 そんな特殊な例外的ケースを除けばラップはもちろん不要
最初からクレート境界を前提とした文脈だろ
>>298 文脈読めよ
インターフェイス vs. ダックタイピング ダックタイピングはインターフェイス名がないため可読性が著しく低い インターフェイス名を使った制約も指定できない 必ずインターフェイス機能を使うべし
ダックタイピングは、意味が異なっていても、見かけの構造さえ同じなら、同一視してしまう問題もある つまりうっかり間違えて用いても、エラーを検出できないため、安全性で劣る。 その見かけの構造さえも、複数の構造を含む場合など、 この型はどのダックタイピングで用いられているのか、読み手が認識するのに時間がかかってしまう。 これらの問題は、各型において、どのダックタイピングに用いられているのかの宣言がないことに起因している。 一方で、interfaceは「各型でどのinterfaceを用いているのか」の宣言があるため、どちらの問題も生じない。
>>333 実行前(コンパイル時など)に問題が表面化することと
実行後に問題が表面化することの違いは果てしなく大きい
>>342 だからRustは清書用って言われるんだよ
>>351-352 type alias でほぼ何でもありな状態に出来るけど
他人のcrateとさらに他人のcrateを混ぜてると詰む
ああ 353 は引用なのか? 354 と 353 が同一人物ならきもいが 354 の言ってることが実情
>>359-360 struct に限ってはそうだね
>>342 Rustでは最初から共通部分があることを意識する必要がなく
そのような場合でも設計の自由度が高い
共通部分が生じたことに後から気付いた時点でそのためのトレイトを後から宣言すればよい
>>354 Rustならばラップは必要なく、トレイト宣言をしてトレイト側へメソッドを移動するだけで簡単に済む
impl Foo {
fn method(&self, ...
}
impl Bar {
fn method(&self, ...
}
と複数の型に共通メソッドがあり、それをトレイトで共通に扱えるようにしたければ
// トレイト宣言
trait TraitName {
fn method(&self, ...
}
// トレイト実装
impl TraitName for Foo {
fn method(&self, ...
}
impl TraitName for Bar {
fn method(&self, ...
}
つまり「impl Foo」から
「impl TraitName for Foo」へ移すだけで済む
今回の例なら差分タイプ量は「TraitName for」のみ
伸びてると思ったら複オジの類友が増えただけだったorz
>>376 structに限らず全ての型に対してトレイト実装によりメソッドを増やせるよ
&str(実質&[u8]でもVec<u8>でも)の末尾に ゴミで良いから毎回必ず'\0'付ける仕様にしといて欲しかった
>>381 '\0'に限らず任意の値を終端として型を定義できるZigの勝利だね
やっぱ崩れたかw 346みたいな偉そうな奴がいるとなw
>>381 必要な時だけ付けりゃいいじゃん
不要なものを常時付けとけとか頭おかしい
異なる方式を混ぜ合わせると両方を協調するのにミスが入りやすい。 ゼロ終端方式とファットポインタ方式に常に矛盾が生じないように維持するくらいなら必要なときに変換するほうがマシ。
>>375 >つまり「impl Foo」から
>「impl TraitName for Foo」へ移すだけで済む
>今回の例なら差分タイプ量は「TraitName for」のみ
フィボナッチみたいなトイコードしか書いたことがないと
こんな意味のない破壊的な変更を無自覚に書いてしまうんだな
>>381 "abc"の部分文字列"ab"を参照する時に元の文字列が"ab\0"になるけどいい?
>>381 &strはStringや(別の)strの任意の部分文字列を参照する型
もし末尾に'\0'を付加すると次の文字を'\0'で上書きするため原理的に不可能
Rustで'\0'終端文字列はCStr/CStringを使う
リテラルならc"ABCDE"
ちなみにC/C++で部分文字列を扱うと
同じ問題が起きるため別領域へコピーして末尾'\0'を付加する
さらに途中に'\0'を置くと千切れる問題や
長さを知るために'\0'まで要走査の問題があるので
Rustのstr/Stringでは'\0'終端文字列としていない
>>387 新たなトレイトを作ってメソッドを移しても破壊的な変更にならない
もちろん移すだけでは意味はないが
使う側でそのトレイト境界を用いてコードの共通化が可能となるため普通に行なわれる
>>391 昔も今もC + +のs t r i n g関数s u b s t r (開始位置, サイズ)は別の領域を確保してコピーだよ
\0終端するためにコピーは避けられないね
ちなみにライブラリ実装依存だろうけど
毎回ヒープ領域確保はコストが大きすぎるため
結果が15文字までならば静的に各16バイトの領域を事前に持っていてそこを使って頑張っていたりはする
でもそこへのコピーは避けられないね
>>390 うわぇー
なんでそんな嘘を吐くの?
もしかして破壊的変更の意味を知らない?
>>391 C++ の中だけでやるなら今は range を中心にライブラリが編成されてるから文字列の一部を取り出すのにコピーは必要ないしゼロ終端も不要だが、ここでは (古いライブラリなり API なりの都合で) ゼロ終端が必要になったときはという前提の話をしてるんだぞ。
外の世界は言語の都合に合わせて勝手に変わってくれたりはしない。
モダンな C++ を使っていても外と繋がる境界では外の都合に合わせなきゃしょうがないんだ。
>>394 Rustの中だけでやるなら文字列の一部を取り出すのにコピーは必要ないしゼロ終端も不要だが、ここでは (古いライブラリなり API なりの都合で) ゼロ終端が必要になったときはという前提の話をしてるんだぞ。
外の世界は言語の都合に合わせて勝手に変わってくれたりはしない。
モダンなRustを使っていても外と繋がる境界では外の都合に合わせなきゃしょうがないんだ。
君の言う前提に沿えば
>>389 の比較は無意味
>>395 「いつの時代の C++ だよ」に対していつの時代でもそうだよと言ってるだけ。
>>389 には興味ない。
>>395 あらためて
>>389 を見たら「ゼロ終端にするにはコピーが必要なのは同じだ (型の整理の仕方は違っても)」というのが趣旨だから結論が同じなのは意図どおりだろ。
>>389 CString::new(string)で0終端してくれて
c"ABCDE"は最初から0終端されてて便利だね
// 固定文字列は c"..." リテラルで作成
let c1 = c"ABCDE"; // &CStr型
// 文字列を組み立てる場合はStringで作成しておいて
let s = ('A'..='E').collect::<String>();
// そのStringを消費して0終端してくれる (途中に0があるとError)
let c2 = CString::new(s).unwrap();
// 左右どちらも &CStr型の c"ABCDE" で一致
assert_eq!(c1, &*c2);
このスレいつからワッチョイとかIDとか無くなった?
ワッチョイとかIDがあると自演するのに不便だからいらない
まともに他人の意見を尊重できる人たちが集まり議論が行われればそこが本スレになるだろうが、期待するだけ無駄じゃろ
>>398 自分で'\0'プッシュすればええやんと以前は思っていたけど
ミスがないことを型システムに保証してもらえる安心感
自分でNULL終端しようとする老害は 安全を保証する型システムと相性悪い
[c_char]が[u8]だと思ってたら[i8]だったでごじゃる
c_charは処理系依存っぽいからu8かi8に決め打ちするならc_ucharかc_scharにキャストした方がいい ターゲット変更した時にコンパイラに文句言われる可能性がある
\0終端じゃないと困るってcやc++から来た人だろ… 老害っているんだな
>>409 OS の要求ならしょうがないだろ……
適当なラッパー作るにしてもそのラッパーの中ではゼロ終端にしないわけにはいかん。
>>398 あとはCString/CStrからの変換だな
&[u8]として扱えるのは当然として
// CStringを消費して Stringとして扱う (非UTF8だとError)
let c = CString::new([b'A', b'B', b'C', b'D', b'E']).unwrap();
assert_eq!(c.into_string().unwrap(), String::from("ABCDE"));
// &Cstrを &strとして扱う (非UTF8だとError)
assert_eq!(c"ABCDE".to_str().unwrap(), "ABCDE");
// &Cstrを Cow<str> にする
// UTF8なら &strとして扱い Cow::Borrowed(&str)型
let cow = c"ABCDE".to_string_lossy();
assert_eq!(cow, Cow::<str>::Borrowed("ABCDE"));
// 非UTF8部分があると U+FFFD置換Stringにして Cow::Owned(String)型
let cow = c"AB\xccDE".to_string_lossy();
assert_eq!(cow, Cow::<str>::Owned(String::from("AB\u{FFFD}DE")));
いずれも'\0'の存在は気にしなくていい
&selfで読み取り参照のまま、別の型の読み取り参照に読み替えるのはもちろん、 selfで消費してしまい、確保メモリをそのまま活用して、別の型に読み替えるのが効率ええんやな
>>
http://2chb.net/r/tech/1708677472/784 Ruby (が採用している CSI 方式) での文字列オブジェクトはそれぞれどの文字コードであるかの情報を持っていて処理系は各文字コードの処理方法を知っている。
つまり文字列を扱うあらゆる箇所で様々な文字コードごとの処理をやってる。
それが先進的か?
文字コードが統一できない世界でも「なんとかする」方法だろ。
内部的には統一した文字コードで扱い、様々な文字コードを扱いたければ入出力の段階で変換するというのが Rust 的なスタイルを含む現代的なプログラムが目指すところで、そのために Unicode はあるゆる文字コードから「変換可能であること」を指向してる。
とはいえ、これが先進的と言えるわけでもなく総合的に考えて現代の事情に合うやり方ってだけだ。
様々な文字コードの変なところも含めて Unicode に取り込んでいるのは既存のテキストのデータを (情報を失うことなく) 移行できなきゃ Unicode に統一されていかないからで、同じ駄目なら統一されていないことによる駄目さより統一されてる駄目さのほうがかなりマシという価値観による。
いろんな駄目さに個別に対処するのではなくデカい駄目に皆で立ち向かう。
人間の言語が数千年・数万年の歴史的経緯の積み重ねなので文字も駄目だし文字コードも駄目。
根本的に駄目なものはどう扱ったって駄目。
綺麗なやり方で扱わないのは綺麗なやり方が存在しないから。。
ネットもファイルもUTF-8で統一しちゃうのが吉 外部のcharset=Shift_JISとか扱わないといけない分だけencoding_rs _io
>>356 >>375 >既にimpl Tにあるのだからimpl Trait for Tへ移動させるだけだぞ
pub 付いてると知名的なので doubt
crateとかdocsの事考えるとそんな単純な話じゃないんだよ 実践的なコード描いてない人か
歴史的にマクロ=悪の固定観念もってるプログラマも多い気がするから macro_rules!()はtemplate!()に改名した方がいいかもしれんね impl Traitとかマクロ使わないと面倒な場合が多い
Rustってfor_eachのclosureのなかでbreak出来ないのです
>>418 名前は Scheme の syntax-rules から持ってきたんだと思う。
>>419 map_whileやtake_whileか
try_for_eachやtry_foldを使えば?
ControlFlowを使って自分で作る方法もある
>>419 クロージャは(変数をキャプチャできる)関数の一種なのでbreakなんて概念はない
for_eachはクロージャを引数に取る高階関数なのでbreakなんて概念はない
次々とやってくる「全ての各エレメント」に対して何度もそのクロージャを呼び出すだけなのでクロージャで早期returnしようとしても全てのエレメントに対して処理される
やりたいことはおそらく次々とやってくるエレメントの途中で処理を終えたいのだろうからfor_eachではなく以下のイテレーターメソッドを使う
>>419 中断条件を分離できるならばイテレータを返してくれる(そして他のイテレータメソッドを繋げられる)以下を使うのがベター take(n) 最初のn個だけ while_some() OptionがSomeの間だけ take_while(f) fが真の間だけ その後に続きを漏れなく使いたいときは take_while_ref_inclusive(f) take_while_ref(f) peeking_take_while(f) map_while(f) 変換しながらfがSomeの間だけ scan(init_state, f) 状態を持ちながら変換しながらfがSomeの間だけ いきなり結果を(ResultやOptionやControlFlowで)返したいならば try_for_each(f) fが中断(ErrorやNoneやBreak)になったら終えてそれを返す 中断なければ()を返す try_fold(init_state, f) 状態を持ちながら同上 中断なければ状態を返す try_collect() iterとitertoolsで仕様が異なりiter版はnightlyのみだけど 中断になるまでをcollect レス:1-200 201-400 401-600 601-800 801-1000 ALL
このスレへの固定リンク: 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本 ->画像>1枚 」 を見た人も見ています:・FUJIFILM X-S10 Part 5 ・DX12 Ultimate対応のGPUは現在NVIDIAとMSだけ、XBOX series Xは2080Tiより上となる ・【ID無し】雑談★468【LE SSERAFlM NewJeans IVE Aespa NMIXX Kepler TWICE NiziU XG BABYMONSTER】 ・【DOAXVV】【IP表示】DEAD OR ALIVE Xtreme Venus Vacation 36日目【DMM/Steam[JP] ・【ID無し】雑談★49【IVE NewJeans aespa LE SSERAFIM NMIXX Kep1er TWICE BLACKPINK NiziU XG】 ・【Microsoft】新ゲーム機 「Xbox One X」発表 UHD BD再生、シリーズ最小筐体で499ドル ・【ID無し】雑談★663【LE SSERAFlM NewJeans IVE Aespa NMIXX STAYC Kepler NiziU XG BABYMONSTER】 ・【ID無し】雑談★382【LE SSERAFIM NewJeans IVE Aespa NMIXX Kepler TWICE BLACKPINK NiziU XG BABY】 ・docomo Xperia Z5 Premium SO-03H Part25 ・docomo Xperia XZ Premium SO-04J Part62 ・【DOAXVV】【IP表示】DEAD OR ALIVE Xtreme Venus Vacation 139日目【DMM/Steam[JP]】 ・【コロナinUSA】新型コロナウイルス アメリカ領グアムで初の感染確認 いずれも60歳以上の3人、うち2人はフィリピンへの渡航歴 ・【ID無し】雑談★74【IVE NewJeans aespa LE SSERAFIM NMIXX Kep1er TWICE BLACKPINK NiziU XG】 ・【DOAXVV】【IP表示】DEAD OR ALIVE Xtreme Venus Vacation 11日目【DMM/Steam[JP]】 ・●○● CHICAGO XIX ★ シカゴ 19 ●○● 【You are not alone】 ★☆★ ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 241日目【DMM/Steam[JP]】 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 123日目【DMM/Steam[JP]】 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 61日目【DMM】 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 72日目【DMM】 ・au Xperia XZ SOV34 Part19 ・【ID無し】雑談★196【LE SSERAFIM NewJeans IVE aespa NMIXX Kep2er TWICE BLACKPINK NiziU XG】 ・キメて xvideos pornhub xhamster ・【ID無し】雑談★106【LE SSERAFIM NewJeans IVE aespa NMIXX Kep1er TWICE BLACKPINK NiziU XG】 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 272日目【DMM/Steam[JP]】 ・【ID無し】雑談★79【IVE NewJeans aespa LE SSERAFIM NMIXX Kep1er TWICE BLACKPINK NiziU XG】 ・【DOAX/集金装置】DEAD OR ALIVE Xtreme Venus Vacation 69日目【カモ歓迎】 ©bbspink.com ・ソニーテンペスト3Dの概要を話す「アトモスのXbox series Xより優れた体験になる」 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 162日目【DMM/Steam[JP]】 ・docomo Xperia XZ Premium SO-04J Part18 ・最新鋭サウンドカード「Sound Blaster X AE-5」が発売、業界初のRGB LED搭載 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 99日目【DMM】 ・Switch版『GUILTY GEAR XX ACCENT CORE PLUS R』発売決定 ・[NPXS] Pundi X Part1 [プンディエックス] ・au Xperia XZ SOV34 Part7 ・【DOAXVV】【IP表示】DEAD OR ALIVE Xtreme Venus Vacation 16日目【DMM/Steam[JP]】 ・【DOAXVV】【IP表示】DEAD OR ALIVE Xtreme Venus Vacation 61日目【DMM/Steam[JP]】 ・〓SoftBank AQUOS PHONE Xx 203SH Part 34 ・docomo Xperia XZ Premium SO-04J Part9 ・【ID無し】雑談★236【LE SSERAFIM NewJeans IVE aespa NMIXX Kep1er TWICE BLACKPINK NiziU XG】 ・インディーの傑作「Slay the Spire」が5月21日に発売決定!!! ・【ID無し】雑談★354【LE SSERAFlM NewJeans IVE aespa NMIXX Kepler TWICE BLACKPINK NiziU XG】 ・【ID無し】雑談★514【LE SSERAFlM NewJeans IVE Aespa NMIXX Kepler TWICE NiziU XG BABYMONSTER】 ・【DAIHATSU】la400kコペン★21台目【Robe XPLAY】 ・【音楽】<ビルボード>桑田佳祐『がらくた』でアルバム・セールス1位!シングル・セールス首位はMONSTA X『Beautiful』 ・【宇宙人狼】Among Us配信者実況スレ Part.19 ・■■ SHARP AQUOS sense3 総合 ■■ Part21 ・サンスイ ■ SANSUI総合スレッド 70 ■ 山水 ・【FSX】Microsoft Flight Simurator X vol.28 ・au WIN Xmini W65S by Sony Ericsson stage 27 ・★CASIO MUSIC GEAR (Z XW SERIES) THREAD PART6★ ・DMM、エロゲー「your diary」でSteamに参入 ・【PS4】BORDER BREAK ボーダーブレイク part275 ・【DOAXVV】DEAD OR ALIVE Xtreme Venus Vacation 302日目 ・iPhone 6 (Plus)であと一年頑張るスレ Part11 ・【宇宙人狼】Among Us配信者実況スレ Part.25 ・ニシ「PS5終わった」サード「PS5、Xbox Series X|S、Steam」 ・【DOAXVV】【IP表示】DEAD OR ALIVE Xtreme Venus Vacation 54日目【DMM/Steam[JP]】 ・【ID無し】NiziU応援スレ Part43【Super Summer】 ・the HIATUS Part63 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 21日目【DMM】 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 26日目【DMM】 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 245日目【DMM/Steam[JP]】 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 35日目【DMM】 ・【DOAX】DEAD OR ALIVE Xtreme Venus Vacation 267日目【DMM/Steam[JP]】 ・【EQ】☆☆ EverQuest ☆☆ Lv55【25th Anniversary】 ・アイカツ STAR☆ANIS AIKATSU☆STARS! 18
19:23:44 up 128 days, 20:22, 0 users, load average: 11.14, 12.46, 12.48
in 1.1428401470184 sec
@0.19301795959473@0b7 on 082408