◎正当な理由による書き込みの削除について: 生島英之 とみられる方へ:C vs C++ vs Rust Part.2 YouTube動画>1本 ->画像>2枚
動画、画像抽出 ||
この掲示板へ
類似スレ
掲示板一覧 人気スレ 動画人気順
このスレへの固定リンク: http://5chb.net/r/tech/1639539350/ ヒント: 5chスレのurlに http ://xxxx.5chb .net/xxxx のようにb を入れるだけでここでスレ保存、閲覧できます。
Goはモダン言語にアレルギー反応が出てしまうC老人のための言語
顔真っ赤な怒り心頭Rustオジサンがなぜかスレタイに無いGoを粘着でディスり続ける
言語仕様が優れてるとかなんとかはあるだろうけど 結局使いものになる言語は何かと言われればC/C++なんだよ
RustとC++が互いに馬鹿にし合うのをCが高みの見物するスレですか?
CやC++なんて、UNIXかWindowsが成功してなきゃ流行ってたわけない (そもそもUNIXがないなら、C言語も生まれてないけど) 結局は勝ち組プラットフォームにおんぶにだっこされてるだけよ Rustも巨大企業に推されて採用されてるから、優れてる言語かどうかに関係なく流行る 流行は巨人が決めてる
May the FORTH be with you.
いまだに組み込みはCオンリーですが、「UNIXがないなら、C言語も生まれてない」は間違いに近い
https://ja.wikipedia.org/wiki/C 言語#歴史
>>8 でもチーム開発するならRustの安全性は100%じゃないとしても十分魅力的だなぁと思う。
>>15 それ読んだら、
UNIXの *ために* C言語が作られたわけじゃないけど、UNIXが *なかったら * C言語も生まれてない、と読めるけど。
>>9 C・・・ベーシックアイテム。
C++・・・おしゃれアイテム。
Rust・・・意識が高くなる壷。
RustやRubyは、まず伝道師から始まるからな。 どういうわけか伝道師が大量発生する。
C++使いがコード書いてる間、彼らは伝道する。 神の使いなのかもしれんな。 啓示があったんだろう。
Rustは実用に主眼を置いた泥臭い言語なので 伝道師の言う美辞麗句は無視してよい
っつか、いくら伝道師わいたってRust自身がその敷居の高さで安易に手を出すやつを排除するからRubyみたいには使われないんじゃねーの?
プログラミング勉強のため素数列を返すイテレータ関数を作ってみました 今回トレイト境界は0と1とoverflow防止足し算と比較演算子のみとなりました use itertools::{unfold, Unfold}; fn prime<T>() -> Unfold<T, impl FnMut(&mut T) -> Option<T>> where T: Copy + num::Zero + num::One + num::CheckedAdd + std::cmp::PartialOrd, { unfold(T::one(), |a| { unfold(*a, |b| { if let Some(c) = b.checked_add(&T::one()) { *b = c; Some(c) } else { None } }).map(|b| { *a = b; b }) .find(|b| !unfold(T::one(), |c| { if let Some(d) = c.checked_add(&T::one()) { *c = d; if d < *b { Some(d) } else { None } } else { None }}) .find(|c| unfold(T::zero(), |d| { if let Some(e) = d.checked_add(c) { *d = e; if e <= *b { Some(e) } else { None } } else { None } }).any(|d| d == *b)).is_some()) }) } 型指定で『i8』(符号付き8bit整数)を与えて実行してみます fn main() { for p in prime::<i8>() { print!("{} ", p); } } 出力結果 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 i8型は127が上限値(2^7-1)なので上手く動作してるようです コードが少し長くなってしまったので冗長なところや改善点など教えていただけると幸いです
>>24 良いコードをご教授していただけませんか?
普通にループは使わずに足し算と比較のみで素数をその型の上限まで返すイテレータ関数です
言語はCでもC++でもRustでも構いませんのでよろしくお願いします
>>25 >>23 ですらループ使ってるじゃん
馬鹿そう
>>27 どこにループが有りますか?
勉強不足でわからないので教えてください
>>29 それは私がプログラミング勉強中だからだと思います
あるいはCやC++ならば「ループを使わずに足し算と比較のみで素数をその型の上限まで返すイテレータ関数」を
綺麗にプログラミングできますか?
綺麗なコードをご教示していただけるとうれしいです
>>23 https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2021&gist=3e0c372e78ce024307bd58c1f03df55e
.find(..).is_some() は .any() と書ける (これはclippyが指摘してくれる)
if let Some(x) = expr { .. } else { None } は let x = expr?; .. とした方がネストが浅くなる
類似の処理は名前をつけて関数に括りだした方がわかりやすい
>>23 https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2021&gist=6d5f63ffe7c46236a0957017db33a0b9
もう少し改善できた
スレ汚しすまん
>>31 のコード見た後に
>>23 見るとゲロ吐きそうになるな
>>28 例えばfindはtry_foldを呼び出してるがこのメソッドはwhileを使って実装されている
どこかにループあるとわかりそうなもんなんやけどな
rustのコードはc/c++以上に見苦しい こんな言語を業界全体でプッシュしてるのは異常だよ
なんでこいつRustの本スレでやらないんだろ、ほんまキモイ
本スレで自己満足やられて本気でウザかったからここでいいよ
>>31 色々とありがとうございます 返り型がOptionだから?を使うとif letを消せるとは気付いていませんでしたw あとそのコードを見ると渡す値を変えないならmapよりinspectを使うといいのですね さらにご指摘くださったfindとis_someを合わせてanyにしたり否定!と合わせてallへ変えたり まだ類似部分の別関数への分離までは進められていないのですがようやくここまで来ました fn prime<T>() -> Unfold<T, impl FnMut(&mut T) -> Option<T>> where T: Copy + num::Zero + num::One + num::CheckedAdd + std::cmp::PartialOrd, { unfold(T::one(), |a| { unfold(*a, |b| { *b = b.checked_add(&T::one())?; Some(*b)}) .inspect(|b| *a = *b ) .find(|b| unfold(T::one(), |c| { *c = c.checked_add(&T::one())?; (*c < *b).then(|| *c)}) .all(|c| unfold(T::zero(), |d| { *d = d.checked_add(&c)?; (*d <= *b).then(|| *d)}) .all(|d| d != *b))) }) } >>34 どうもありがとうございます 調べて勉強します >>35 >>42 これ全く同じ機能をC++だと美しく書けるんかいな?
前スレでもRustの動くコードは出ていたがC++の動くコードは全く出てこなかったよな
だから既にC++プログラマーは絶滅していてRust派とアンチRust派(数学100点マン等)だと思ってた
unfold使ったこと無いから間違ってたら教えてほしいんだけど これO(n^4)?
さわやかな新宿の朝って感じですね。 ゲロの臭いでもらいゲロしそう。
>>44 違うと思います まずunfold自体はループするものではなくこれだけです struct Unfold<S, F> { s: S, f: F } fn unfold<S, F, R>(s: S, f: F) -> Unfold<S, F> where F: FnMut(&mut S) -> Option<R> { Unfold { s, f } } impl<S, F, R> Iterator for Unfold<S, F> where F: FnMut(&mut S) -> Option<R> { type Item = R; fn next(&mut self) -> Option<Self::Item> { (self.f)(&mut self.s) } } 次に今回のコードで使われているunfoldについてですが 一番外側のunfoldは上述の構造体を返すだけになります 次のunfoldは素数でない数をスキップするだけで残り2つがO(n^2)となるでしょうか どの言語で書いても足し算のみ使用だとこれは避けられないかと思います あとコードが汚いとおっしゃる方は同条件で綺麗なコードを示してくださるとありがたいです CでもC++でもRustでも構いません そもそも 「ループを使わずに足し算と比較のみで素数をその型の上限まで返すイテレータ関数」 というのはどこからでてきたもんなんだ? この条件になにか意味があるの?
>>48 まず素数なら列になるのでイテレータにするのはいいですよね
用いる型によって上限値が異なるから上限まで返すのも自然ですよね
足し算と比較は必要最低限として不可欠だと思います
どうしてもならばループは使ってもいいですよ
だから今回は可能ならばループを直接使わずに高階関数イテレータ使用でという話だけです
つまりそんな難しい話をしているわけではないと思います
他の言語のコードが出てこないのは難しいからなのでしょうか?
Rustのことは知らんのだけどsome, any, map, findって実質ループじゃないの? Rubyっぽい構文も見られるけどブロックを毎度呼び出してもらってるだけだからループじゃないとかいうわけ?
>>50 登場していたSomeは値付きenumなのでデータの型です mapは変換するだけなのでそれ自体にループ要素はないです 一方でfindなどはループを内包している高階関数になりますね だから>>49 にて「今回は可能ならばループを直接使わずに高階関数イテレータ使用」と書いたのです 宿題となっていた類似部分を別関数へ切り出しが出来ました これでわかりやすくなったでしょうか? fn prime<T>() -> Unfold<T, impl FnMut(&mut T) -> Option<T>> where T: Copy + num::Zero + num::One + num::CheckedAdd + std::cmp::PartialOrd, { unfold(T::one(), |a| { inc(*a, T::one(), |x| x > T::zero()) // 無条件に+1していき次の素数を探す .inspect(|b| *a = *b) // unfoldのため値更新 .find(|b| inc(T::one(), T::one(), |x| x < *b) // 自分より小さい数で+1していき約数を見つける .all(|c| inc(T::zero(), c, |x| x <= *b) // その約数の候補を自分以下で足し算していく .all(|d| d != *b)))}) // 自分が倍数になっていなければOK } fn inc<T>(s: T, a: T, f: impl Fn(T) -> bool) -> Unfold<T, impl FnMut(&mut T) -> Option<T>> where T: Copy + num::Zero + num::One + num::CheckedAdd + std::cmp::PartialOrd, { unfold(s, move |x| { *x = x.checked_add(&a)?; f(*x).then(|| *x) }) } >>49 人に読ませるためのコードを書いたことがないのかな?
アルゴリズム的にどうとかRustの書き方的にどうとか言う以前の問題
>>51 めっちゃ理解しやすくなったな まるで宣言型論理プログラミングっぽい雰囲気だ 説明の日本語はこう書くとよい //素数とは自分未満で次を満たす約数を見つけること .find(|b| inc(T::one(), T::one(), |x| x < *b) // 条件は約数の倍数すべて(自分以下)が .all(|c| inc(T::zero(), c, |x| x <= *b) // 自分と一致しないこと .all(|d| d != *b)))}) 本スレでクソコード連投してた奴だな 素数列挙をジェネリックにしてうれしがるセンスが厨二病っぽい
>>17 DEC PDP-11で動かすUNIXを書くためにC言語が生まれたと思ったが?
C言語の方が後なら、最初のUNIXは何の言語で書いてあったの?
>>58 Wikipediaにすら「当初はアセンブリ言語のみで開発されたが、1973年にほぼ全体をC言語で書き直した。」と書かれているんだけど。
>>18 要するに
Cはマック
C++はスタバ
Rustはブルーボトルって理解でおk?
>>55 ご指摘ありがとうございます 変数名を英語やローマ字にしてもわかりにくかったため日本語にしました あとは無駄な部分を整理した結果シンプルになりました fn 素数列<T>() -> impl Iterator<Item=T> where T: Copy + num::One + num::CheckedAdd + std::cmp::PartialOrd, { range(T::one(), |_| true) .filter(|&素数| range(T::one(), |約数| 約数 < 素数) .all(|約数| range(約数, |約数倍数| 約数倍数 <= 素数) .all(|約数倍数| 約数倍数 != 素数))) } fn range<T>(unit: T, cond: impl Fn(T) -> bool) -> impl Iterator<Item=T> where T: Copy + num::CheckedAdd, { itertools::unfold(unit, move |x| { *x = x.checked_add(&unit)?; cond(*x).then(|| *x) }) } fn main() { itertools::assert_equal(素数列::<i8>(), [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127]); assert_eq!(素数列::<u8>().last(), Some(251)); } コードが汚いとご批判くださっていた皆さま方 これでいかがでしょうか? マジで何がしたいんだろこいつ 使えなさ加減は似たようなものだが 計算量を重視するだけ競プロ信者のほうがまだマシ
コードゴルフみたいなパズル感覚なんじゃね 知らんけど
言語の構文が受け付けないというとこの話を思い出す
http://love-motif.com/article/art_13.shtml rustの構文に対してこんな感じで生理的嫌悪覚えてるんですか?
rustが流行って、こういう素数なんて書く意識高い初心者が量産されて、汚ねぇコードを治すのかと思うと 今から頭痛がしてくる
>>61 Rustは晋三が飲んでる何とか還元水では?
意識タッケーーー!!!
>>65 今どきは他のプログラミング言語も似たようなものだぜ
例えば配列 [4, 9, 3, 7, 1, 8, 5] から文字列 "9-8-7-5-4-3-1" への変換
【Ruby】
a.sort().reverse().map{|x| x.to_s}.join('-')
【JavaScript】
a.sort().reverse().map(x => x.toString()).join('-')
【Rust】
a.iter().sorted().rev().map(|n| n.to_string()).join("-")
このように些細な違いのみでほとんど一緒
逆に古典的な記述法は以下のようにコードが読みにくい
【Python】
'-'.join(map(lambda x: str(x), reversed(sorted(a))))
【Rust】 a.iter().sorted().rev().map(|n| n.to_string()).join("-") これはどんなアセンブリコード吐くの?
>>72 Rustでは最小限しかstdに入れない方針
use itertools::Itertools; を付ければ
>>69 で通る
>>67 どう見てもめちゃくちゃ意識低いやつのコードなんですけど・・・
どこに意識高い系要素を見出だしたんだ?
>>71 Rustの各イテレータメソッドは全て各々の固有の構造体(struct)を返すだけです
アセンブリコードはスタック上に確保された構造体の大きさの領域にその値が入ることになるでしょう
そしてその構造体に対してnext()という関数が実装されています
後続の別のイテレータが自分に対してそのnext()を呼び出すことになります
そして他からnext()を呼ばれた側は自分の構造体のデータを利用して値を返します
これらのアセンブリコードは普通の関数呼び出しと同じでしょう
具体例を見たほうが早いと思います
例えばもう少し簡単な以下の例を動かしましょう
fn main() {
let v = vec![5, 6, 7, 8, 9];
v.my_iter().my_print();
}
このベクタvに対してmy_iter()さらにmy_print()とチェーンになっている例で説明します
多くの場合はライブラリにあるイテレータを使うので自分で実装しなくていいのですが
アセンブリコードが気になる(=どう動作しているの?)とのことなのでゼロから実装します
このmy_iter()も構造体を返すだけの関数です
ここでは説明をわかりやすくするためジェネリックでなく
具体的な型『Vec<i32>』(符号付き32bit整数のベクタ)に対してmy_iter()を実装します
まずmy_iter()が返す構造体を定義します
struct MyIter {
vec: Vec<i32>,
index: usize,
}
ベクタの値を次々と返していけるようにベクタとそのインデックスを保有します
変数名と型の位置がC言語とRustでは逆なだけでわかると思います
インデックスのための型『usize』は符号なし整数です
そしてmy_iter()の関数をVec<i32>に対して実装します まず以下のtraitの部分は今回おまじないとして無視していいです trait MyIterTrait { fn my_iter(self) -> MyIter; } 次が関数my_iter()のVec<i32>に対する実装(impl)です impl MyIterTrait for Vec<i32> { fn my_iter(self) -> MyIter { MyIter { vec: self, index: 0 } } } このように関数my_iter()は>>75 で定義した構造体MyIterを返しているだけです アセンブリコードはC言語などと同じになるでしょう ただしC言語では構造体はポインタ返しのみだったと思いますが Rustでは構造体をそのまま返せてこれはスタック領域にデータが返ります あとは冒頭に説明しましたイテレータとして機能するためのnext()が必要です 構造体MyIterに対してイテレータの実装(impl)をします impl Iterator for MyIter { type Item = i32; fn next(&mut self) -> Option<i32> { if self.index < self.vec.len() { let ret = self.vec[self.index]; self.index += 1; Some(ret) } else { None } } } ベクタの現在のインデックス値を Some(ret) と返しているだけです インデックスがベクタの長さを超えたら None を返しています ではこの>>76 の構造体MyIterのnext()は誰がいつ呼ぶのでしょう? ここではメソッドチェーンになっているので後続のイテレータが呼びます 具体的には>>75 で v.my_iter().my_print(); でしたからmy_print()が呼び出します そこで関数my_print()の定義です 今回もtraitの部分はおまじないと思って無視していいです trait MyPrint { fn my_print(&mut self); } 下記で任意のイテレータに対して関数my_print()を実装(impl)します そのためこの部分だけはジェネリック指定『<I: Iterator>』のコードをご容赦ください 後ろのwhere以降の std::fmt::Display は表示を許可するためのおまじないと思ってください impl<I: Iterator> MyPrint for I where I::Item: std::fmt::Display { fn my_print(&mut self) { while let Some(val) = self.next() { println!("{}", val); } } } ここでmy_print()のselfというのはここでimpl対象=先行するイテレータすなわちMyIterになります もちろんMyIter以外の別のイテレータに対してもこのmy_print()は機能します 今回の使い方ではselfは構造体MyIterになりますから whileのところにあるself.next()も先程定義したMyIterのnext()になります next()の返り値が Some である限りprintln!で表示して None になるとwhileを抜けて終了です 以上で冒頭の以下の例の全てコードが実装されましたので動きます fn main() { let v = vec![5, 6, 7, 8, 9]; v.my_iter().my_print(); } 今回
>>77 のmy_print()はメソッドチェーンの最後なので構造体を返していません
だから正確にはmy_print()はイテレータではなくイテレータに実装されたメソッド(の一つ)という立場だけです
逆に言えばメソッドチェーンの途中の全てのイテレータメソッドは各々の固有の構造体を返します
そして後続のイテレータ(など)からnext()の値を要求されたらそれを返す動作のみするのがイテレータです
長いメソッドチェーンで一番最後がnext()を要求して連鎖的に最初のnext()が呼ばれるパターンもよく有ります
なぜなら多くのケースで途中のイテレータは自分のnext()実装で先行するイテレータのnext()を呼び出すからです
そして連鎖的にnext()呼び出しが生じても動作原理は多段の関数呼び出しと同じです
したがって元の質問
>>71 「どんなアセンブリコード吐くの?」も
「イテレータとして機能するメソッド呼び出しは単なる関数であって構造体を返すだけ」と
「あとで後続からその構造体に実装されてるnext()関数が呼ばれる」だけなのです
特別な仕組みとか裏でインタプリタやランタイムや魔法が密かに動いている、ってことはないです
文章を構造化できない人はコードを構造化することもできない ひとりよがりが過ぎる
>>79 では修正点や改善点などをお待ちしておりますw
どんなアセンブリコード返すのという質問なんだから
>>72 みたいにアセンブリ示せばよかろうに
イテレータの作りを説明してくれた人ありがとう それ自体は他の言語でもよくあるパターンだね ただ聞きたかったのは効率を重視するはずの(と思っている)言語が この書き方で効率のよいコードを吐けるかどうかってこと >a.iter().sorted().rev().map(|n| n.to_string()).join("-") Rustはimmutableが基本と言う話を聞いてるからもしかしたら 新しいオブジェクトを生成しまくってるんじゃないかと思ったんだよ この書き方をしてC/C++と同レベルの効率のコードが吐けるのかなって
>>84 そのコードは to_string() を要素数だけ呼んで最後に join してるからヒープアロケーションの回数が気になる場合は使うべきでないコードだね
だだrustのイテレーターのメソッドチェーン自体は不要なヒープアロケーション行わないしメソッドはインライン展開できるので
ある程度複雑なメソッドチェーンでもfor文と同じようなアセンブリになると言われているよ
>>84 例えばCのfor文などと比較すると、
その変化していく変数は構造体の中だが大元の関数のスタック上すなわちローカル変数と同じだからCと変わらん
あとinline展開指定されてるものなどで関数呼び出しオーバーヘッドも消えて前後のコードが繋がって最適化されるパターンもある
だから気にせずに使っても誤差範囲
>>85 結局メソッドチェーンとは別問題として
一般的にVecやStringなどのヒープ使うものがループ内にあると注意やな
あとcollectでスタック使うArrayVecやArrayStringを指定する手もあるな
>>69 > 配列 [4, 9, 3, 7, 1, 8, 5] から文字列 "9-8-7-5-4-3-1" への変換
> a.iter().sorted().rev().map(|n| n.to_string()).join("-")
このコード自体は他言語との類似比較のために冗長に書かれていて無駄がある
join("-")はDisplay実装あれば通るから事前のto_string()は不要
つまりa.iter().sorted().rev().join("-")でOK
さらにsorted()はヒープに結果Vecを確保する
もし元を書き換えていいならヒープ確保をjoin()でのString一つだけで済む
let mut a = [4, 9, 3, 7, 1, 8, 5];
a.sort();
assert_eq!("9-8-7-5-4-3-1", a.iter().rev().join("-"));
このrev()を無くすためにa.sort_by(|x, y| y.cmp(x))にするとcmp関数でやや不利
一方でrev()使用は配列やVec相手ならDoubleEndedIterator実装があるからコストかからない
現実にはこのコードが核心部分でなければそこまで気にしなくていいけどな
一つだけアドバイスしとくけど、ジェームス・ボンドが日本人だったら、大木・凡人だからね。
>>74 Rustを使ってればカッコイイという錯覚で、何も分かってないのに汚物のようなコードと意味不明な長文をまき散らす…
あんなに単純な初期のJavaやC#でさえスパゲッティコードだらけなのに、日本語の説明さえも気持ち悪い
>>91 こじらせてんな
ゲロコード君とは違う方向性だが
長文二人は属性が似過ぎだろ こんなのが二人もいればRustスレが気持ち悪くなるわな
顔真っ赤で根拠も反論もない「こじらせてんな」マンが永遠と長文や短文を書き、本Rustすれに代わりキチガイを集めるスレ
>>91 >あんなに単純な初期のJavaやC#でさえスパゲッティコードだらけなのに、日本語の説明さえも気持ち悪い
文の前半と後半のつながりが全くわからないので解説頼む
> この難しさを取り除くために、Rustは、C/C++の落とし穴を排除し、その過程で使いやすく役に立つ > 洗練された一連のツールを提供します。 低レベルな制御に「下がる」必要があるプログラマは、 > C/C++のクラッシュやセキュリティホールのリスクを負わず、 気まぐれなツールチェーンのデリケートな > 部分を学ぶ必要なくRustで同じことができます。さらにいいことに、 Rustは、スピードとメモリ使用の観点で > 効率的な信頼性の高いコードへと自然に導くよう設計されています。
顔真っ赤Rustオジサンの「 >」、やっぱ同一人物だったかw
>>84 その、新しいオブジェクトを生成しまくってるんじゃないか、の意味が曖昧なので
自動的にヒープ領域から動的に新たなメモリ確保をすると解釈すると、それはないです
Rustでもプログラムで明示的に指定しない限り勝手にそういうことが起きることはありません
もちろん例えばVec型(伸長可能な配列)やString型(伸長可能な文字列)を新たに返す関数を使えば
それはプログラムで明示的に指定したことになり、当然ヒープ領域が使われます
一般的にイテレータの長い連鎖があっても各イテレータが返す(=用いる)構造体は各1つで
それらはコンパイル時に静的に確定してスタック上にローカル変数と同様に領域が確保されます
したがってイテレータ連鎖で動的にヒープが使われうるのは例えば
(1) イテレータがクロージャを引数として取る場合にそのクロージャのコードがヒープを使うものである場合
(2) sorted()のように前イテレータから全要素を一旦受け取る必要がある途中のイテレータが一時格納場所としてヒープを用いる場合
(3) collect()のようにイテレータ連鎖の最後に全要素を収集してVecやStringなどを新たに生成する場合
いずれもそれらの関数やクロージャをプログラムで使用した時のみ、動的にヒープが使われます
何が気持ち悪いかというと 自分も知らなかったことを調べてきてさも知ってたかのように上から目線でレスする精神 気持ち悪い そしてその内容がいつも間違えてるからゲロ吐く気分になる
多少の間違いがあっても要点をおさえて質問に正面から答えてるんならまだいいんだけどねー 困ったもんだ
間違いがあれば俺が指摘修整してやるから安心しろ おまえら雑魚はそれでいい
おまえは間違ってるって主張だけだと数学100点の人と同じだぞ せっかくだからどこが間違ってるか指摘してあげなよ
そいつらは前スレからそんな感じだから放置されてる ガイジとかゲロとか汚などの言葉を好む 具体的なコードや具体的な指摘は出来ないダメな連中
プログラム勉強しはじめたんだけど、CとかC++よりもRUSTのほうがかっこよさげだからRUSTやってる
CやLispからはじめるのが意識高い系 Rustからはじめるのはカッコつけたいだけの単なる無知
ウッホウッホホ、マウンテンゴリラです。得意なのはドラミングで毎日ドコドコやってます
最近c++勉強始めたんだが、cとかmapも使えないじゃん どうしてんの?
RustはコンパイラもライブラリもRustで書かれているね
>>116 昔はアルゴリズムの教本を参考にして全部1からつくってた
今も必要があれば車輪の再発明をする能力を持つ人と持たない人にプログラマーは二分される 前者は新たな枠組みを作ることも可能な生産者 後者は既存の枠組みを使うだけの消費者
プロデューサーとコンシューマーと呼ぶと両方存在して初めて意味を持ちそうな感じがするな
この場合の生産者は、制作者(プロデューサー)ではなくて創造者(クリエイター)の方が近い
もっともらしく言ってるけど 新たな枠組みを作ることができるかどうかに 車輪の再発明をする能力は関係ないよ
プログラミングにおいて車輪の再発明すら出来ない人が プログラミングにおいて新たな枠組みを作るのは無理
ザッカーバーグとかツールレベルでいえばあるもの使ってただけだがな。
クイックソートくらいは自作してみたほうがいい 最初混乱するだろうけど、ああなるほど!となった時に必ず経験値に加算される筈だ
>>128 そりゃ彼はプログラミングにおいて新たな枠組みを作ったわけではないからな
新たな枠組みって例えば何? フレームワークのことではなさそうだけど
例えば画像データの取り扱いでbitmapをそのまま処理していたような時代にpngやjpgなどのアルゴリズムをはじめて考え出して 実装したようなプログラマが新たな枠組みを作ることが出来る人 既存のライブラリ使って画像処理や表示のアプリを実装しているようなプログラマが枠組みを使うだけの人
もちろん例としてプログラミングのフレームワークでもいいんじゃね? 例えばそのザッカーバーグの例ならば Facebook社はプログラミングにおいて新たな枠組みとして世間にも広まるほどのReactを作った 一方でザッカーバーグ自体はReactを今から車輪の再発明すらできないしプログラミングにおいて新たな枠組みを作れないだろう
枠組みに限らず何か新しいもの自力で作るには その対象レイヤーのものを作れる能力は必要 それは当たり前 ザッカーバーグだって掲示板システムを実装する能力があったからFacebookを作れたわけだが それを「車輪の再発明する能力」と呼ぶのかどうか 「新しい枠組み」と「車輪の再発明をする能力」の定義が曖昧すぎて中身がない
結局のところ 「低レイヤーの開発をするには低レイヤーの実装能力が必要」という主張でしかない
そこは定義でもめるから深入りしない 例えば例に挙げたReactは自分の観点からは低レイヤーではなく高レイヤー 結局これでいいかね? 各分野のプログラミングにおいて車輪の再発明すら出来ない人が その分野のプログラミングにおいて新たな枠組みを作るのは無理
車輪の再発明って何 自身で模倣できる程度には理解しているということ?
レイヤーは相対的なものだよ 低レイヤーで通じないなら下位レイヤーとでも言おうか Reactのユーザーから見ればReactそのものの開発は下位レイヤー Reactを作るために下位レイヤーのJavaScriptエンジンやレンダリングエンジンを再発明できる能力が必要か?
話はシンプル それぞれの分野で見ればよい Reactの分野だったら 『自分でウェブフロントフレームワークを簡易なものでよいから作ったことあるか?あるいは作れるか?』 これだけの話 つまりReactの開発者たちと同じような立ち位置に立てるプログラマーなのか、 それともReactの消費者としてユーザーの立場のプログラマーなのか、の違い
まとめると 「新しいウェブフロントフレームワークを作るには ウェブフロントフレームワークを作る能力が必要」 そりゃそうだ 話はシンプルシンプル
なんだよこれ遅っせーなー 意味分かんねーんだよこの挙動 俺のほうがもっとうまく作れる
消費者プログラマーは色んな仕組みをわかっていなかったり理解できなかったりする人が多いね そうなると車輪の再発明すらできないし車輪の改良もできない もちろん車輪に代わる新たな仕組みを作り出すこともできない
元の話はmapの実装方法がわからない、だから、もっと深刻な状況なのか プログラミングする上での基本的なことは 車輪の再発明であろうと自分でやってみて体験していくべき
習熟のために必ずしも車輪の再発明が必要であるわけではないでしょ
発明する必要はないけど何もないところから自分の力だけで車輪を組み立てられるようにはなっておいた方が良い
「フロントフレームワーク」なんて言い方するのかとググったら、まぁまぁ居たわ
IPアドレスの正規表現を再発明してるやつがいたけど ああいうのが"新しい枠組みを作ることも可能な生産者"だったのかw
IPアドレスの仕組みも正規表現も別に目新しいものではないのでは? 何か特別な表現手法とかを導入する余地って残されていたか?
正規表現とか言ってもただの文字列だからな 数式やアルゴリズムに落とし込めないもので再発明も何も手の出しようがないだろ
使ってる言葉を自分なりに定義できないやつは普段物事を深く考えてない 知性の程度を簡単に測れる物差し
>>151 えっ?
正規表現⊆アルゴリズム
じゃない?
ただの検索や置換のためだけのメタ言語だよ 問題記述能力はない
>IPアドレスの正規表現を再発明してるやつがいたけど 再発明って具体的にどういうことやってたことを言っているんだろ
そのケースはアルゴリズムではないな 一般的に自分で一から作れる人はその時々に応じて最適なアルゴリズムを見つけ出すだろう
何がアルゴリズムで何がアルゴリズムでないか ちゃんと境界値テストできてる?
俺がすごいと思ったらすごいというのをいかに客観的評価のように見せるか議論しているようにしか見えない
>>163 その通り
ついでに「俺すごい」アピールをしてる
まあ議論には全くなってないがな
>>161 一般的には(決定性)チューリング機械で可能な処理のことだけどな。
なので一部の数式(無限大集合とか)は範囲外。
無限大を数値計算で扱うために優秀なソフトエンジニア達の手によって、例えば離散フーリエ変換や離散ウェーブレット変換などのアルゴリズムが工夫され考え出された これが新しい枠組みを作り出すということ
>>167 FTは無限大集合を扱っている訳では無いだろ。実数とか扱えないし。
周期信号のフーリエ級数展開なら有限だけど連続信号を扱うなら無限積分の計算が必要 FTは無限積分を数値計算するため分割統治のバタフライ演算に落とし込んで更に演算量を抑えるため各種のアルゴリズムが考案されてる
で、新しい枠組みを作り出すことが C vs C++ vs Rust にどう関わってくるの
枠組みを作ることは凡人には無理 殆どは枠組みを使う人 ただ枠組みの仕組みを知らないと使うことも出来ない
最早スレチの話題に突っ込んで悪いけど、無限積分を回避できている気になっているのは気のせいであって、バタフライ演算とか関係ないからね(笑)
以前に皆さま方からアドバイスをいただいて 『足し算のみで素数列を生成するジェネリックなイテレータの実装』 を当時O(N^3)という酷さでしたが、このたびほぼ O(N) の新たなアルゴリズムと実装が出来ましたのでご報告します 足し算の総回数を O(N log log N) すなわちほぼ O(N) 近くにすることに成功しました 具体的には 1億(=10^8) までの素数生成に必要とする 足し算の総回数が 2.5億回 とリニアになりました 前回と異なりメモ化をしていますがこちらも工夫により配列の長さを O(√N / log N) に抑えることに成功しました 具体的には 1億(=10^8) までの素数生成に必要とする 配列の長さが 1231 と非常に小さな領域のみで実現できました 10^kまでの素数を順に生成時の足し算の総回数 O(N log log N) 10^1 4.70×10^1=47 10^2 2.03×10^2=203 10^3 1.90×10^3=1903 10^4 1.95×10^4=19508 10^5 2.12×10^5=212715 10^6 2.27×10^6=2278220 10^7 2.41×10^7=24148110 10^8 2.54×10^8=254082528 10^kまでの素数を順に生成時の配列の長さ O(√N / log N) 10^1 4 10^2 6 10^3 13 10^4 27 10^5 67 10^6 170 10^7 448 10^8 1231 メモリ使用もこの程度の少なさで 足し算を2.5億回とその比較だけで1億までの全ての素数を順に出力できるようになりました このスレは数学が得意な方々が多いようなのでご検証よろしくお願いします
今回は読みやすいようにループで記述しました impl<T> Iterator for 素数生成Iterator<T> where T: Copy + num::Zero + num::One + num::CheckedAdd + std::cmp::PartialOrd, { type Item = T; fn next(&mut self) -> Option<T> { '次候補: loop { self.新素数 = self.新素数.checked_add(&T::one())?; if self.新素数 == self.倍数[self.上限] { self.上限 += 1; if self.子.is_some() { self.素数.push(self.子.as_mut()?.next()?); } self.倍数.push(二乗(self.素数[self.上限])); } for index in 1..self.上限 { while self.倍数[index] != T::zero() && self.倍数[index] < self.新素数 { self.倍数[index] = self.倍数[index].checked_add(&self.素数[index]).unwrap_or(T::zero()); } if self.倍数[index] == self.新素数 { continue '次候補; } } break; } if self.子.is_none() { self.素数.push(self.新素数); } Some(self.新素数) } }
上述に「子」とあるのはメモリ節約のためのテクニックで 「子」と「孫」を再帰的に利用しているためです 「自分」だけで必要なメモリをNとすると 「子」を利用することでメモリが√Nで済むように設計しました また、 self.上限 が配列の長さで self.新素数 が1億(=10^8)まで進んだ時点で self.上限 が 1231 です self.上限 が更新された時のみ、つまり1億までで1231回だけ コードにあるように以下の二乗する関数が呼ばれます fn 二乗<T>(n: T) -> T where T: Copy + num::Zero + num::One + num::CheckedAdd + std::cmp::PartialOrd, { let mut count = T::one(); let mut result = n; while result != T::zero() && count < n { count = count.checked_add(&T::one()).unwrap(); result = result.checked_add(&n).unwrap_or(T::zero()); } result }
fn main() { assert_eq!(vec![2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127], 素数生成::<i8>().collect::<Vec<_>>()); assert_eq!(65521, 素数生成::<u16>().last().unwrap()); assert_eq!(78498, 素数生成::<u32>().take_while(|&p| p < 1000000).count()); } fn 素数生成<T>() -> 素数生成Iterator<T> where T: Copy + num::One + num::CheckedAdd { let 孫 = 素数生成Iterator::<T>::new(None); let 子 = 素数生成Iterator::<T>::new(Some(孫)); 素数生成Iterator::<T>::new(Some(子)) } struct 素数生成Iterator<T> { 素数: Vec<T>, 倍数: Vec<T>, 新素数: T, 上限: usize, 子: Option<Box<Self>>, } impl<T> 素数生成Iterator<T> where T: Copy + num::One + num::CheckedAdd { fn new(子指定: Option<Self>) -> Self { let three = T::one().checked_add(&T::one()).unwrap().checked_add(&T::one()).unwrap(); Self { 素数: vec![T::one()], 倍数: vec![three], 新素数: T::one(), 上限: 0, 子: 子指定.map(|子| Box::new(子)), } } }
コードは以上です
今回はitertools::unfold()を用いなかったため、それにより省略できていた、
「イテレータ用構造体の宣言」「その初期化」「そのIteratorトレイト実装宣言」
などが今回は必要となりコードがその分だけ長くなっていますが
イテレータの実装本体部分は
>>174 のみです
足し算の総回数が O(N log log N) 例: 素数を1億までで2.5億回
メモリは配列の長さが O(√N / log N) 例: 素数を1億までで長さ1231使用
これらを足し算のみで実現できています
どうぞご検証よろしくお願いします
嫌われ者Rusterのウザウザ全文貼り付け、見るのも嫌になる自己満足オナニー
なんかやたら足し算のみで、って強調してるけど、 アルゴリズムはエラトステネスの篩だよね? そう言ってくれたほうが理解しやすいよ Rustはまだあんま良くわかってないのでコードは参考になるかも でもテストケースに127が入ってるのはおかしくない?
アルゴリズムに興味がある場合はCが読みやすいということがよくわかった
1億までの素数を全て求めるのが2.5億回の足し算だけで出来るものなのか?? メモリもエラトステネスだと1億必要だよな?
>>182 1億回の素数判定を個別に考えると平均2.5回の足し算となりもちろん無理です
そこで過去の判定時で用いた足し算の結果を後の判定時に用いる方法で
結果的に平均2.5回の足し算で済ませています
また、単純にエラトステネスのふるいでは1億の長さの配列が必要となりますが
まず時間と空間を逆転させることで必要となる配列の長さを減らしています
さらに再帰的に子と孫のイテレータを活用することで
>>173 の表のように1億(=10^8)まで判定時で配列の長さ1231に抑えています
その時点で子と孫では配列の長さ27となっています
>>183 そんなO(N)のペースでメモリを使用していくのはいずれ限界もありますし
メモリキャッシュヒットの観点からも望ましくないと思います
さらに今回は小さい方から順に素数を返すイテレータです
イテレータ利用者は1億を超えて素数を利用するかもしれませんし
逆にもっと少ない小さい数のみ利用するかもしれません
最初に上限が1億など決まって開始する古典的エラトステネスのふるいでは上手くいかないのです
キャッシュヒット率の話するならベンチマークとってくれ
わざわざ決まってる数列を順番に出力するイテレータ書くのにそんな記述が必要になるのか ちょっと普通のループでいいからC言語で書いてみてよ
>>185 ベンチマークをとる前に実装が必要だな
その前に新たなアルゴリズムも必要か
エラトステネスの篩は「指定された整数以下の素数を求めるアルゴリズム」だからイテレーターとは相性が悪そうだ
イテレータにすると、プログラミングの方向が変わるんですよ。 詳細を未来に先送りできるんです。 伝統ある手続き型の手法では、システムやライブラリを書く人が詳細を実装し、使う人は大まかな指示を出しましたよね。 イテレータ手法は、未来に詳細を決定する。 つまり使う人が細かいことを決める事になるんです。 そこらへんの詳しい話は、書籍クリーンアーキテクチャに載ってます。 この本に書かれてることがすべて正しいとは言いませんが、正しいことにしろ間違ってることにしろ、読んでおいて損はないです。
イテレータ特有の話と言うより遅延評価全般の話に読めるが
イテレータ万能説を唱えて長文するガチキチおじさんwww yieldはgeneratorをレイトバインド for(range)はiteratorをレイトバインド async/awaitはfutrueをレイトバインド 詳細を未来に先送り!キリッw
クリーンアーキテクチャを出してるから遅延評価のことじゃなく IoCの一例としての高階関数のことを言いたいんじゃないかな?
昔は局所化して先送りにできることは素晴らしいことだと思ってた でも最近そんなのは些末な事で、無能な働き者が気にすることだったなと考えを改めた 木を見て森を見ずと言うべきか
>>188 ある意味その考え方も正しいかもしれませんが
イテレータは例えば大ざっぱに分けても5種類はあるので
自分が作る部分がどの部分かによってその立場も変わると思います
(1) 発信イテレータ …
>>174 で示しました素数生成、レンジ(0..n)、配列やVecに対するiter()などチェーンでは先頭に来るもの
(2) 仲介イテレータ … map()、filter()、enumerate()などチェーンでは中間に来るもの
(3) 受信イテレータ … find()、fold()、collect()などチェーンでは最後に来るもの
(4) 合成イテレータ … chain()、zip()、merge()など複数のイテレータを入力とするもの
(5) 創造イテレータ … unfold()などイテレータを生み出す汎用イテレータ
とりあえず(4)(5)は置いとくにしても自分が作る部分は用途によって(1)か(2)か(3)と変わるため大きく立場も異なります
>>189 一般的に遅延評価による先送りといえば主役はクロージャですね
上述したイテレータを作り出すunfold()もクロージャを渡すことで成立しています
>>190 futureは「未来に先送り」ではなく「未来を先取り」と捉えたほうがよくないでしょうか
そして遅延評価というよりも並行並列評価する形になりますね
したがって今回の話には適さないかなと思います
>>186 > わざわざ決まってる数列を順番に出力するイテレータ書くのにそんな記述が必要になるのか 決まってる数列ではなく毎回算出するんですよ 記述については各々のイテレータはそれぞれ何らかの構造体にすぎないので >>176 に示しましたように 「(a) イテレータとなる構造体の型宣言」「(b) その構造体の初期値定義 new()」「(c) 今回は自分と子と孫がいるためその関係記述」 があってようやく、>174に示しました「(d) イテレータ自体の毎回の算出コード」がそこに加わります 一般的にも今回の特殊な用途(c)を除いた3つ(a)(b)(d)は必要です さらに>>195 でいうところの仲介型イテレータはそれらの記述に加えて 「(e) 他のイテレータのメソッドとなりチェーンできるようにするための宣言」がさらに必要となります 上述(a)(b)(d)の部分の記述だけならば お手軽にイテレータを生成できる itertools::unfold() を使えるケースだと 例えばフィボナッチ数列を返すジェネリックなイテレータは 以下のように初期値と処理クロージャを1つunfold()に与えてやればイテレータを作れます fn fibonacci<T>() -> impl Iterator<Item=T> where T: Clone + num::Zero + num::One + num::CheckedAdd + std::cmp::PartialEq, { itertools::unfold((T::one(), T::one()), |(m, n)| { if *m == T::zero() { // overflow return None; } // shift: ret <- m <- n <- next let next = m.checked_add(&*n).unwrap_or(T::zero()); let ret = m.clone(); *m = n.clone(); *n = next; Some(ret) }) } >>185 そのためにもぜひ異なるアルゴリズムの実装を作ってくださるとベンチ比較できますね
いまのところ足し算で素数生成するイテレータの実装は以前に作った明らかに非常に遅い
>>62 と
今回作った動作O(N log log N)でメモリ使用量O(√N / log N)となる
>>174 の2つしかないのです
>>187 そうなんですよ
エラトステネスのふるいは最初に上限数を指定するためそのままではイテレータと相性がよくないです
またメモリ使用量も大きくなってしまいます
そのため試行錯誤のうえ新たなアルゴリズムが生まれたのが今回の実装です
もっと良い方法を考えついた方は教えていただけるとうれしいです
より良い方法に興味があるんなら、普通に既存実装を研究してみたらいいんじゃない?
例えばRubyの標準添付ライブラリにも Prime.each があるよ
ソースはここ
https://github.com/ruby/prime おれはそこまで素数のアルゴリズム自体には興味ないから考えないけど
C/C++/Rustならどの言語も理解できないほどの特異な書き方や奇妙な省略もなくどれも似たようなもんだ どれか一つで書かれていれば普通のプログラマーなら読めるだろう それでもわからない部分があれば質問したら皆が教えてくれるぞ
>>195 ええその通りです。
ですから使いどころを間違っていると思うのです。
>>200 普通のプログラマじゃなくて雑魚なんで
Rustで書かれたコードはわからないしRustの説明が欲しいわけじゃない
C/C++で書かれてれば説明無用だから全部わかるならC/C++で書いてくれない?
Ruby の無限generator は、遅延評価する。lazy 普通に、メソッドチェーンを左から処理していくと、 無限に処理できないので、右から処理していく 素数は、6 で割って余りが、1 か5 余りが3なら、3で割り切れる。 余りが2, 4なら、2で割り切れる
if (25 % 6 == 1) { //25は素数? }
>>205 さすがに必要条件と十分条件がわからないのはどうかと思う
>>207 6で割って余りが1か5になるのは素数であることの必要条件や
xが素数⇒x%6=1,5
その事実を利用してまずは数を6で割って余りが1 or 5のとき 改めて素数かどうかを判定する関数に通すってことか? rem = X % 6 if ((rem == 1 || rem == 5) && is_prime(X)) { // Xは素数 } else { // Xは合成数 }
>>195 発信、受信、仲介、合成、創造?
コンピューターサイエンス分野を見てもRust公式を見てもそんな用語は1つもないけど
それってもしかしてあんたの個人的な思想ですか?それなら知りたくないのでウザいので黙っててもらえますか?
したがって今回のRustオジサンは気持ち悪い基地外だと思います
>>213 気持ちはわかるけど最後の一文が個人的な気持ちになってて同じ穴の狢になってない?
>発信、受信、仲介、合成、創造 たしかにこの用語なんなん? どっから出てきたの? どの界隈のコンセンサスで得てる言葉なの?
イテレーターを作ったことがない初心者プログラマーには理解が難しいと思うが
命名はともかくイテレーターがそのように分類されることは俺でもわかるぜ
>(1) 発信イテレータ …
>>174 で示しました素数生成、レンジ(0..n)、配列やVecに対するiter()などチェーンでは先頭に来るもの
これはRustだとimpl Iterator for XXXのみ実装のイテレーター
つまり他者のnext()は利用せずに他者に対してnext()を提供
>(2) 仲介イテレータ … map()、filter()、enumerate()などチェーンでは中間に来るもの
これはRustだとimpl Iterator for XXXおよびimpl XXX for Iteratorと両方実装のイテレーター
つまり他者のnext()を利用しつつ別の他者に対してnext()を提供
>(3) 受信イテレータ … find()、fold()、collect()などチェーンでは最後に来るもの
これはRustだとimpl XXX for Iteratorのみ実装のイテレーター
つまり他者のnext()を利用するが他者に対してnext()を提供せず
以前に議論されていた消費者プログラマー(?)だと区別を一生気付かないままかもしれぬ
>>218 デザインパターンのMediatorとかでは聞いたことあるのでは
>>220 2-4あたりをひっくるめてiterator adaptorというのはよく聞くけど細かい分類は
>>195 の造語っぽい
>>220 知らん
しかしプログラマーとしてはそれらの違いは必須の知識
なんせ真逆だからな
impl Iterator for XXX
impl XXX for Iterator
>>222 わざわざ知らない役をやって同調するバカをおびき寄せてから知ってる役をしてるってか?
しねーよ
足し算で素数を求めるアルゴリズムについて知りたいんだが誰かC/C++で書ける人いないの?
独自に分類名を付けようとする試みは評価するが チュートリアルに書いてるレベルの内容で 「初心者プログラマーには理解が難しいと思うが」とか言っちゃう初心者プログラマーはどうかと思う
公式用語はsource、adapter、consumer
イテレータはライブラリ作者と利用者の間でループをやり取りするには便利なものです。 しかし、それ以外で使ってもパッとしない。
>>203 >>210 素数列の生成でそんな何度も割り算しまくるような無駄はしないはず
そんなことしていたら足し算平均2.5回のより遅くなってしまう
>>228 素数が足し算平均2.5回程度で求まるアルゴリズムを説明してくれないか?
Rustという世界最高の言語があるのに、なぜRubyを使うのが正しいのか。 リーン・スタートアップという本を読めばわかるよ。
Ruby on Railsは、GitHub, Airbnb, Disney, Hulu, SoundCloud, Shopify といった世界的に有名な企業や、 日本国内でも、note、クックパッド、freee、マネーフォワード、Progate、Qiita などで使われている 2021年10月には、GitHubのコピーで、Railsを使い続ける宣言をしている、 GitLab が上場し、時価総額は約1.9兆円! 一方、GitHubはGo へ以降する Railsを使う理由を端的に言えば、もうかるから Ruby biz Grand prix 2020 大賞を受賞した、Ruby の女神・池澤あやかも言ってる。 他の言語では開発者を確保しにくいので、Railsに切り替えた
>>214 仲介手数料、信用創造、お前が同じ穴の狢、アホのRustオジサンです
>>173 1億までの素数を全て生成するのに足し算2.5億回で済む理由がわかった
素数でなければ1万以下の素数が約数として必ずあるから順に最大素数9973まで調べるだけでよい
1億/2 + 1億/3 + 1億/5 + 1億/7 + 1億/11 + … + 1億/9973 = 約2.5億の足し算で原理的には済むはず
>>224 ある数がある数で割れるかどうかのテストに足し算を使っているだけ。
例えば12を3で割れるかどうか調べる場合、0 3 6 9 12と足し算していって、12が見つかったので割れる。
エラトステネスの篩、のことなのでは? でも1億分のバッファとか、勿体ない気がしますね…
発見済みの素数を使ってループして数Xが素数かどうかを調べてるだけだろ? 足し算平均2.5回って意味不明なんだが?
>>239 1億までの素数列挙の場合が足し算平均2.5回なだけじゃね?
>>173 を見る限り
100万までの素数列挙なら足し算平均2.2回
1万までの素数列挙なら足し算平均1.9回
足し算の回数はO(N log log N)とあるから多少増えていくのだろう
そう書いていたら謎が解けた
>>235 > 1億/2 + 1億/3 + 1億/5 + 1億/7 + 1億/11 + … + 1億/9973 = 約2.5億の足し算で原理的には済むはず
これは1億✕(1/2 + 1/3 + 1/5 + 1/7 + 1/11 + … )だから括弧内は素数の逆数の和でlog log N
1億がNだから足し算の回数はO(N log log N)なのか
>>239 素数かどうかを調べるのは
>>236 が書いているように足し算だけで可能です
必要となる足し算の数は
>>241 が書いているようにO(N log log N)です
足し算平均2.5回は1億まで素数を列挙した時の話であって
>>240 が書いているようにNに対してわずかですが増えていきます
>>242 C言語でいいから加算で素数を求めるアルゴリズム書いてくれない?
>>244 その日本語wikiは怪しいので英語のwikiを見るといい
100回繰り返すのと1億回繰り返すのとどっちがマヌケに見えるか、億という言葉を使えば賢く見えるのか? 億回繰り返さないと理解できないのか、汚コードRust相談室と化したC vs C++ vs Rustスレに未来はあるのか
>>244 実際のコード例で体験していくと理解が早い
例えばこの計算をしたいとする
>>235 > 素数でなければ1万以下の素数が約数として必ずあるから順に最大素数9973まで調べるだけでよい
> 1億/2 + 1億/3 + 1億/5 + 1億/7 + 1億/11 + … + 1億/9973 = 約2.5億の足し算で原理的には済むはず
コードは
>>176 の素数生成イテレータも使って以下のイテレータ4つの連鎖で求まる
let result: i32 = 素数生成::<i32>()
.take_while(|&p| p < 10000)
.map(|p| 100000000 / p)
.sum();
途中のtake_while()は条件を満たす間だけ取るイテレータでこの場合は「1万未満」が条件
map()は変換するイテレータで「素数pを1億/p」へ変換している
最後にsum()で流れてきた1億/pを「全て足して」目的を達成
このように個々の単機能イテレータを複数組み合わせて連鎖させることでプログラミングできる
まーたイテレータの定義をよくわかってないやつがヘンテコな説明しちゃう
ヘンテコなとこに気がつけなかったんだけど、どのへん?
今どきの言語のイテレータは
>>248 で合っている
しかしC++のイテレータは低レベルでポインタを抽象化したものと考えたほうがいいので注意
C++にもようやくmap()に相当するものが入ったが他言語とは異なりtransform()という名前など使いにくい
今どきのプログラミングしたいなら素直にRustを使ったほうが便利
>>250 イテレータとは何かを分かってない
用語の使い方見れば一目瞭然でしょ
分かってない人が書いた説明を読むよりもある程度査読されてる英語のwikiや各言語のリファレンス見たほうがいい
この文中に>>入れる自作自演の同一人物の基地外Rustのくせはほんと気持ち悪い。また引用で > 使う
伝統的には値を生成するものはジェネレータと呼ぶわな
>>254 それは観点が違うな
値を生成するものであってもイテレータとして機能するものと機能しないものがある
つまり重要な点はイテレータとして機能するか否かのみ
Rustの1..nやこのスレの素数生成はイテレータとして機能しているから明白にイテレータ
やっぱり頭がおかしいよ、1..nはRange { start: 1, end: n }と同じ。Rust公式でもイテレータじゃなく 単にRangeと言っているだけなのに、それが機能するかという観点ならfor inが無ければ機能しないから イテレータじゃない。collect()がイテレータをコレクションに変換するように、for inで(暗黙)変換されるだけ。 こいつ、あちこちで暴れてる
RangeはIterator実装してるからrustの定義ではイテレータではあるのでは
>>258 君もイテレータがわかってないお仲間さんなので仲良く勉強しとけ
プログラミング初心者でもないのにイテレータを理解してないやつがRustスレに多いのはなぜ?
ここ本スレではなく隔離スレ スレ民の目的はただの冷やかし
"仲介イテレータ" 約 2 件 (0.26 秒) すげー、全世界で、このスレにしかその言葉は存在しない
>>262 一番レスの多い自演厨が理解してないから、そう見えるだけ
イテレータには狭義のイテレータと広義のイテレータがある
広義のイテレータは狭義のイテレータとイテレータメソッドを合わせたものである
(A) イテレータ(狭義)
Rustで言えばtrait Iteratorを実装するもの
コード上で「impl Iterator for 各イテレータが返す型」となって現れる
各イテレータが返す型は通常structでありimpl Iterator<Item=T>を満たす
メソッドとしてnext()を持ちこれがOption<T>を返す
(B) イテレータメソッド
Rustで言えば上述イテレータ(狭義)のメソッドとなるもの
コード上では「impl 宣言用トレイト for Iterator」の中で現れる
各イテレータメソッドが返す型は任意でありfor_each()のように無しもある
対象となったイテレータ(狭義)のnext()を利用する側となる
>>195 | (1) 発信イテレータ …
>>174 で示しました素数生成、レンジ(0..n)、配列やVecに対するiter()などチェーンでは先頭に来るもの
| (2) 仲介イテレータ … map()、filter()、enumerate()などチェーンでは中間に来るもの
| (3) 受信イテレータ … find()、fold()、collect()などチェーンでは最後に来るもの
その分類で言えば
(1) = (A) かつ not (B) = イテレータ(狭義)だが イテレータメソッドではない
(2) = (A) かつ (B) = イテレータ(狭義)であり イテレータメソッドでもある
(3) = not (A) かつ (B) = イテレータメソッドだが イテレータ(狭義)ではない
>>267 >広義のイテレータは狭義のイテレータとイテレータメソッドを合わせたものである
この定義のソースはどこ?
素数生成君と仲介イテレータ君は同一人物だったのか どおりで
>>267 > Rustで言えばtrait Iteratorを実装するもの
これは無理矢理名前をつけるとすれば Iteratee と呼ぶべきでイテレーターではないのでは
こいつ何度間違っても全く反省しないなww 良い子は鵜呑みにしないで自分で調べようね
>>270 詫びがてら説明しておくがイテレータは数えあげる人のこと
「次くれ」→ 「はい、どうぞ」
「次くれ」→ 「はい、どうぞ」
「次くれ」→ 「もうありません」
数えあげる対象物を数えあげる人自身が持ってる場合もあれば持ってない場合もある
impl Iteratorしてるのがイテレータなのは間違いない
>>270 君の中ではそうなのかもしれないが
世間では
>>267 の(A)をイテレータと呼んでいる
そしてイテレータパターンでもnext()を持つものをイテレータと呼んでいる
したがって
>>267 の説明で正しい
デザインパターンの一つであるイテレータパターンの説明図 (wikipediaより)
next()を持つものがイテレータ
つまり
>>267 の定義で合っている
視野が狭く思い込んだら多くの人が警告しているのに完全に無視し「定義」だの仲介だの創造だの自分勝手に講釈を垂れる
Rust公式Bookでも同じ
https://doc.rust-jp.rs/book-ja/ch13-02-iterators.html 全てのイテレータは、標準ライブラリで定義されているIteratorというトレイトを実装しています。
Iteratorトレイトを実装するには、Item型も定義する必要があり、
そして、このItem型がnextメソッドの戻り値の型に使われています。
イテレータに対して直接nextメソッドを呼び出すこともできます。
じゃ
>>248 が間違ってたんだね
素数生成イテレータ
take_while()イテレータ
map()イテレータ
sum()イテレータ
4つの単機能イテレータの連鎖で求まるだっけ?
>>267 に照らし合わせると
上3つが狭義のイテレータ
下3つがイテレータメソッド(広義のイテレータ)
って感じかね
間違ってるとまでは言えまい
イテレーターの定義はIteratorを実装してる型で良いと思うがそれがどう C vs C++ vs Rust に繋がるのか
>>280 そりゃ間違ってた本人の言い訳定義だからな
御本人さんよ
イテレータメソッドというのは多くの言語では一般的にはイテレータを返すメソッドのこと Java, C#, C++, JavaScript, Python, Ruby, Scala等々 RustではIterator Trait’s Methodsの意味で “iterator methods”という言葉が使われるがこれは訳すなら”イテレータのメソッド” Rustに限った話でもIterator Traitの個別メソッドを ”イテレータ”と呼んでるのはnext()を除いて聞いたことがないので 広義のイテレータを定義してるソースがあるなら提示してもらいたい
>>283 必死こいて言い訳のソースを調査中だから期待して待っててね
javaだと public interface Iterator<E> ここにあるメソッドをiterator methodsと読んでる人居るね まあ単にイテレータのメソッドってことなんだけど
>イテレータメソッドというのは多くの言語では一般的にはイテレータを返すメソッドのこと ググってみたがほとんど用例が見つからん。
ばっかもーん!それがイテレータだ!定義しろ〜! みたいな
>>284 いいわけが見つからず
必死に話題そらしを始めるに1000ペリカ
たしかに「イテレータメソッド」だと「イテレータ生成メソッド」を意味する用例もあり曖昧さがある 「の」を入れて「イテレータのメソッド」とした方がいいだろう (A) イテレータ trait Iteratorを実装するもの コード上で「impl Iterator for 各イテレータが返す型」となって現れる 各イテレータが返す型は通常structでありimpl Iterator<Item=T>を満たす メソッドとしてnext()を持ちこれがOption<T>を返す (B) イテレータのメソッド イテレータのメソッドとして機能するもの コード上では「impl 宣言用トレイト for Iterator」の中で現れる イテレータの各メソッドが返す型は任意でありfor_each()のように無しも可 対象イテレータのnext()を利用する側となる
// 例: イテレータ CountUp struct CountUp(isize); impl Iterator for CountUp { type Item = isize; fn next(&mut self) -> Option<isize> { self.0 += 1; Some(self.0) } } // 例: イテレータのメソッド average() trait AverageMethod { fn average(&mut self) -> isize; } impl<I: Iterator<Item=isize>> AverageMethod for I { fn average(&mut self) -> isize { let mut len = 0; let mut sum = 0; while let Some(n) = self.next() { len += 1; sum += n; } sum / len } } fn main() { let a = CountUp(0).take(99).average(); assert_eq!(a, 50); }
反応がないとうんこしたと流してない。不安に襲われるような感じ
>>291 のイテレーターとメソッドをCやC++で実装することも可能ですか?
どんな感じのコードになりますか?
ここにいるRust屋はC/C++が書けないってことがはっきりしている
単純にC++が不得手な分野が多すぎ Rustだと楽に書けるからこのスレに書かれているコードがRustばかりになっている プログラミング言語としての優劣の違い
Rustだと楽にかける分野ってメモリ安全性関連以外ない気がする
Rustはイテレータ作れる文法用意されててスゴイ言語ってことか まあトイプログラム作るのに秀でた言語いじって喜んでるレベルじゃ あらゆる分野のアプリケーションが書かれてきたC++の実績は理解できないだろうな せいぜい不得意なことと言えばスクリプト言語で代用される分野くらいだろ
>>297 パターンマッチがハマるプログラムは書きやすいと思う
言語処理系とか
>>299 なるほど
でもそれってc/c++でもenumと構造体か共用体組み合わせればできるよね?
>>297 マルチスレッドは楽だと思うけどな
というかC++が辛すぎる
>>300 できるできないの話じゃなく
どちらが楽にできるかの話をしてたんじゃないの?
C++20 からコルーチンが入ってジェネレータは割と書きやすくなったよ
とはいえイテレータのほうが従来通りのポインタ的用法に引きずられてるからなんともだけど
https://cpprefjp.github.io/lang/cpp20/coroutines.html >>300 c++でもできるけどenumの値とunionのvariantの組み合わせはプラグラマが意識しないといけない
rustだとmatch式のcond部分に値を書けばrust-analyzerがすべてのarmのスケルトンを作ってくれるから
穴埋めしていくだけで処理が書けて楽
>>304 まあrustの方がc++よりパターンマッチング楽なのは認めるよ間違いない
C++と比べてRustだとメモリ安全にできるから、スレッドセーフなコードも誰でも書けるよ そういったメモリ安全関連の利点がなきゃ存在意義のない言語だよね 書いたコードが高速に動作するかどうか、とかはまた別の話だけど
>>301 マルチスレッドの並列処理だけでなくシングルスレッドマルチタスクの並行処理も便利かつ安全に書けるところも
>>304 match式だけでなくletやif letでのデストラクチャリング&マッチングがある点も
一方でC++は多重構造の分解分配もダメでif letも値付きenumもないからほとんど何も出来ない
>>298 C++で書けることは全てRustで書ける
C++が優位な点は過去実績しかない
これは両方やればはっきりと認識できる
そのスクリプト言語的な記述や利便性がRustにあるという認識は正しい
かゆいところにも手が届くスクリプト言語という側面もある
>>306 CやC++と同等の性能特性を持つ言語の選択肢は限られてるから安全性以外の理由でRustが採用されることもあると思うよ
Rustって循環参照安全に書けないんじゃなかったけ?
>>308 構文のアーム「=>」や後置のifガードなどRustのmatch式の後追いパクリw
それが仮に導入できても要である値付きenum(=タグ付き共用体)を持たないC++では活用に限界
>>312 曖昧すぎてどういう状況で何が書けないとの主張かわからないけど
C/C++で安全に書けることはRustでも安全に書ける
つまりRustで安全に書ける範囲の方が完全に広い
>>313 C/C++にはRustでいうところの安全(⇔unsafe)はないから "C/C++で安全に書ける物" が何を意味するかわからない
そもそも
>>309 の "C++で書けること" や "Rustで書けること" ってどう定義されるの?
Rustのmatch式はScalaの後追いパクリw
プログラミング言語としての比較結果は明瞭 適用可能な範囲は同じかつ最速 いずれもGCがなく低レベル操作も可能 Rust = C++ = C したがって勝負は他の点 コード記述が楽に簡潔に書けるか Rust > C++ > C 安全なコードを書けるか保証できるか Rust > C++ > C
>>318 > いずれもGCがなく低レベル操作も可能
これはRustはnightly使うこと前提?
低レベルな機能についてはまだまだunstableなものが多いので少なくともstableなRustではC/C++でできること (処理系依存なものも含む) がすべてできるとは言えないのでは
https://doc.rust-lang.org/stable/unstable-book/ 新たな(pre-)RFCも日々提案されてるし現状で十分とあぐらをかくべきではないと思う
ということは、RustはC++よりJavaと比較する言語なのでは?
>>309 の
> C++で書けることは全てRustで書ける
を念頭に置いた話で "全て" は言い過ぎ、C++でないとできないこともあるだろうと言いたかった
CやC++の低レベル操作は Rust でも "だいたい" できて大抵のユースケースでは困らない
と言うのが正確だと思う
Java は GC あり VM 言語だから低レベル操作の観点でのRustとの類似度で言ったらCやC++の方が近い
メモリーの安全性を強調する言語と言えばJavaが筆頭に挙げられるのでは? Javaは実行時最適化を行うのでC++より速いと主張されます。 この点もRustと酷似している。
JavaもRustもC++と比較した優位性を主張するのですが、JavaとRustならどちらが優れているのでしょう?
>>319 勘違いしてないか?
それらのほとんどは既に別の手段でコードを書くことができるが更に利便性を高めようと検討されている機能だぞ
C++で言えば
>>308 提案のマッチングは現在できないがそれが無くとも別の手段でコードは書ける話
>>320 C++とRustは適用可能な範囲が同じ
Rustの記述性能が高いという違いしかない
>>322 Javaはガベージコレクションがあり適用可能な範囲が狭い
さらにヌルポインタ例外もありJavaはメモリ安全ではない
Javaは組み込みにも使われ、それどころかpico javaというJavaを効率よく実行できる組み込み用プロセッサのアーキテクチャ迄あるんですよ。 完全にRustと一致するじゃないですか。 実績を考えたらRustを完全に包含しています。 なぜJavaとの比較を嫌がるのですか?
もしかしてRustはJavaに負けているのですか?
GCがあってデータ競合も起きないマルチパラダイム言語で、C,C++以上の爆速で動く処理系があるとするならそら優秀だろうと思うわ Javaは実際にはそんなに爆速じゃないだろうし、データ競合の対策がしやすい言語とも思えんけど
活気があったころは、C++と比較して20倍速いと主張するサイトもありましたよ。 まさに爆速です。 Rustと似ています。
安全性という観点では、RustはHaskellと似ているように思います。 熱心なHaskellユーザーはコンパイルが終わればバグが無いことを保証されると主張します。 Rustと全く同じです。
Javaを含めるとこうなる 安全なコードを書けるか保証できるか Rust > Java > C++ > C Javaはヌルポインタによる参照でエラー例外が実行時に起き得る Rustはそれさえも起きない したがって速さだけでなくメモリ安全の点でも Rust > Java が確定済 Javaが勝てる点がない そのためJavaを捨ててRustへ移行するプロジェクトもある
Haskellもまた、C++と比較して優位性が主張されることの多い言語のひとつです。 しかし、JavaやRustと比較されることは一切在りません。 Java、Rust、Haskellでは、どれが最も優れているのでしょう?
でもRustはJavaより遅いですよね? Javaは実行時最適化によりC++より20倍速いことがbenchmarkで判明していますよ。 10年以上も前に。
C++を改良したD言語もあります。 DとRustならどちらが優れているのでしょう?
出自からして、D言語もまたC++と比較して優位性が述べられる言語のひとつです。 しかし、RustやHaskellと比較されることは在りませんね。 どちらが優れているのでしょう?
まずは決定的な違いを勉強しなさい GCのない言語 Rust C++ C GCのある言語 Java D C# Go Haskell Python Ruby JavaScript ...
>>335 GCの有無で何が変わりますか?
JavaやRuby、Pythonは組み込みにも使われますし、宇宙にだって行きます。
Rustよりずっと広範囲に使われています。
Rustで作られた実用的なソフトウェアはFirefoxしかないじゃないですか。
しかも、そのFirefoxだって熱心な信者以外誰も使わない。
それと比較したら、これらの言語は実用的に使われています。
GCが在ろうとなかろうと。
>>324 大体代替手段があるのはそうだと思います
例えばnaked functionやglobal_asmは別途asmなりCなりからオブジェクトファイル生成してリンクするという代替手段があります (これがありならC-FFIできる言語は皆同等になってしまいますが...)
もともと C++ でできることは "全て" できるというかなり強い主張をされてた人がいたのでそれは言い過ぎじゃないかと言いたかっただけです
>>332 ご参考まで
https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/java.html 他の言語との比較もありますよ
Rustのポジションに取って変わりたいなら、RustみたいにLinuxのKernelコードに取り込まれていってくれるとわかりやすいんだけどね なぜC++を含む他の言語はLinux Kernelに採用されないのか、って考えると差が明瞭になってきそうだ
Firefoxのバグの多さを考えても、Rustはバグを生産する言語のように思います。
>>336 RubyやPythonは遅すぎ&メモリ食い過ぎで話にならない
例えばクックパッド社はRubyで書かれていたのをRustへ置き換えて経費節減に成功している
そういえば Windows 10にRust使う話ってどうなったんだろうか
>>336 以下の記事にメモリ安全な既存の言語ではだめでCやC++やRustでないといけない理由
それらの中でもRustが良いとされる理由が書かれていますよ
https://msrc-blog.microsoft.com/2019/07/22/why-rust-for-safe-systems-programming/ >>339 FirefoxについてC++コードをRustに書き換えたらセキュリティに関わる脆弱性数がどうなるか分析した記事がありました
https://hacks.mozilla.org/2019/02/rewriting-a-browser-component-in-rust/ 結論としては完璧ではないけどRustの方がバグを減らせるということのようです
MS ResearchやGoogleのAndroidチームも類似の調査をやっていてRust採用は効果有りと判断しているみたいです
JavaやHaskellも多くの人がC++より優れていると分析しています。 速く容易で安全なのです。 全ての点でC++を上回っています。 では、それらの言語を比較した場合、どれが最も優れているのでしょう?
ほとんどすべての言語がC++より優れていると主張します。 という事は、C++はもっとも劣った言語のひとつなのです。 Rustはもっとも劣った言語より優れていると主張しますが、優れた言語、例えばJavaやHaskellと比較したら、かなり劣っているのでは?
多くの人がRustとC++と比較している 比較するなら優れたもの同士を突き合わせるはずだ なのにJavaやHaskellは影も形もないつまり論外ってことだ 全ての言語がC++に対して優位性を主張するのも C++が最も現実的で優れた言語だと認めているからであって わざわざ劣っているものと比較する必要なんてないからだ
>>344 JavaやHaskellがC++より常に高速というのは明確に誤りです
https://benchmarksgame-team.pages.debian.net/benchmarksgame/index.html ではC++がこれらの言語より優れているかというとそうではありません
言語にはそれぞれ得手不得手があります
唯一絶対の尺度で優劣を決めようとするのではなく、ある特定の用途に対してどの言語が適しているかという観点で議論した方が生産的かと思います
GitHub・Cookpad などは、遅いRuby on Rails から、Go・Rust などへ移行している 2021年10月には、GitHubのコピーのGitLab が上場し、時価総額は約1.9兆円! こんな大きい時価総額でも、Railsを使い続ける宣言をしている 基本、Railsは中小ベンチャーが、高品質なサービスを作るツール。 2億レコード・取引先が2万社みたいな規模でも、問題ないと言ってた 他には、組み込みのmruby の本も出た。 Webで使えるmrubyシステムプログラミング入門、近藤宇智朗、2020/11 宇宙開発などの組み込み用、MicroPython, Lua, Squirrel の代替になる。 Ubuntu 18.04, C99 対応 人工衛星イザナギ・イザナミで、使っている
C++もJavaも実行時にnull pointerによる参照が起きる可能性があるためどちらも安全性に劣るよね Rustではenum Option使用でnull pointerによる参照が絶対に起きないことをコンパイル時点で保証した上で コンパイル後は最適化でOptionがNoneの時にnull pointerを使うという二段構えにより Rustはコストをかけずに無駄なく安全性の保証を実現しているところに感動した
null安全ぐらいはモダン言語なら当たり前の機能なので、もはやメリットとは感じないわ 例えばTypeScript、Swift、Kotlin、Haskellとか
C++とJavaが前近代的でダメな言語なだけだよな
Haskellは安全性と並列化を追求した言語です。
RustはHaskellの長所である型クラスをトレイトとトレイト境界で採り入れていたり HaskellのMaybeモナドやEitherモナドを採り入れてRustの型の核としているところにも感動した
システムプログラミングでCに代替となれるほどRustがイケてるのは、 null安全やメモリ安全はモダンな言語だから当然として、データ競合が起きないことも保証しつつ、実行速度もCに劣らなくて、 それでいてRustと多少のアセンブラだけ使えば、OSや組み込みソフトウェアも普通に記述できるほどフットプリントの小さい低レベルな言語だから
システムプログラミングにはJavaのほうが向いています。 単純に速いからです。 Javaは宇宙でさえ使われる安全で実績のある言語です。 しかも速い。 実行時最適化を行わない言語では無理な速さです。
結局RustはHaskellの真似をするだけの偽物言語にすぎません。 Haskellの並列性、安全保証を移植するには、結局Haskellになるしかないのです。 RustはいずれHaskellになるでしょう。 その時もまだRustと呼び続けるのでしょうか。
rustのnull安全?はクリティカルコンテキストでも保証されるんか?
現状でRustの欠陥は指摘なしなのか まあ優れた言語だから主流になるとも限らんけど ここはRust礼賛が多くて参考にならんな
>>360 キチの相手するならメールかなんかでやってくれ
良いという人だって使ったことないんだから、欠点なんか出てこないよ。
int型(32ビット)でyy/MM/dd/HH/mmの形で日時を実装しているプログラムは、2022年1月1日0時0分(2201010001)に32ビットの最大値(2147483647)を越えてしまい、エラーが発生する。そういう実装をしているMicrosoft Exchangeでは既に問題が発生中。 みんな仕事始めになって気づいて大騒ぎに
>>367 ハードウェア割り込みの割り込みコンテキストのつもりで書いた
社内独自用語なんだと思う
そこは気にせんでくれ
>>361 Rustのポインタ(参照)および実体にはnull/nil/undefined等が一切ない
そのためnull問題が起きることはなく所謂null安全が保証されている
nullになる可能性がある場合は汎用のオプション型であるenum Option<T>型を用いる
このOption<T>はenumとしてSome(T)とNoneの二値を取り型Tは任意な型
つまり所謂NullはenumのNoneで表現され型Tとは異なるためnull問題が起きようがない
これで効率やコストはどうなるのか?
null(RustではNone)が使われない時は型Tのまま扱うので従来と同じ
null(RustではNone)が使われうる時は型Option<T>として扱う
型Option<T>から型Tを使うにはNoneでない確認が必要だがこれこそ必須な確認コスト
ポインタ(参照)の場合は値がnullすなわち0になることがないためコンパイル後はNoneが0で表現される最適化となる
つまり結果的にはC/C++と同じになるのだがRustは上述のようにコンパイル時点でnull安全を保証できる点で異なる
ぬるぽ例外が発生するから安全じゃないとか言う書き込みがあった。 これはウソ。 ないほうが良いならCはヌルポを検出できないから安全って事になる。 Javaは検出して例外を発生させるから安全なのです。 キチガイに騙されるな。
>ないほうが良いならCはヌルポを検出できないから安全って事になる。 発生したことを検出できないことと発生しないことを意図的に混同している
Firefoxの惨状を見れば全然安全でないことがわかるのに。 なぜ安全と言い張るのか。
CもC++もJavaも実行時にヌルポ発生するからいずれもダメ Rustは実行時にヌルポ発生しないことが保証されているから安全
RustアンチがRustを称賛してるのではないか。
このようにRustをやってる奴は性格が捻じ曲がってる
rustってc++より難解だよな こんな言語が流行るとは思わない
他の言語と比べればめちゃくちゃ難解だし、Rustコミュニティでもどうすれば簡単になるのかいろいろ議論されている
ワイじゃないけど必死に褒めてるのにアンチだとか、ウジ沸いてる
Rustファンも、こんなスレに書き込みしないで初心者向け解説でも書けばいいのにな。
必須じゃないけど他の言語も知らないRust初心者が異常に増えてきているからトンチンカンな推しをするだけで コミュニティの増加は良いことだが、初心者が書いた意味不明なコードを直すのはあんたら Null安全系の推しをしてるのはド素人
メモリ安全が守れればすべてが安全と謳ってる連中は原発は止めれば安心安全とほざいてた奴等と瓜二つ
>>386 そもそもRustはメモリリークが起きないことは保証してくれない
参照カウントが循環参照にならないようにしたり、不要になった参照が残り続けたりしないようにするのはプログラマの責任
なのでプラグラム側になんらかのバグがあったのではないかと
メモリ管理周りを標準ライブラリやOSに全部任せられる普通のアプリケーションとは違って
全部自分でやらなきゃいけない自作OSだからバグなく作るのは難しいというのはあるかと思う
>>389 結局C++と同じで習熟甘いやつが作れば問題起きまくりなの?
>>387 Rustを含めていまどきの言語がnull安全なのは常識
むしろC++やJavaが古すぎて様々な点で時代遅れにすぎない
もちろんRustはもっとその先へダングリングポインタ排除とGC排除を両立した点にある
このように攻撃性と倒錯を丸出しを両立してしまうと初心者っぽさが出てとても引っ掛かりやすい どこで覚えたのかNull安全からダングリングポインタという関連性がない事を言い出す。 ゴミくずが降り積もっていく・・・
>>391 一般的にメモリ関係諸問題のうちメモリリークのみはGC利用でしか解消と判明している
しかし一方でRustではメモリリークを起こすのも意図的にしか起こせない
Rustには所有権の概念があるため特別に複数の所有権を認める特別な参照を
自分で明示的に使用した上でさらに循環参照を生じさせた時のみメモリリークが生じうる
もちろんそのような場面でも通常は弱参照を併用するためメモリリークは起きない
>>386 自分で独自OSのランタイムやGCを作って
その上で稼働させるアプリがリークを起こすかどうかは
アプリだけじゃなく作ったランタイムやGCのロジックに依存するよね
nullで落としてるようなバカがnull安全な言語使っても同じく死亡するコード作るだけにしか思えんがな。 あれで救えるコードなんてほとんどないと思うが。
もっとその先へ!草 上のOS記事の作者はリークというかフラグメンテーションの発生だと推測してるが絶対読んでないね。 「意図的にしか起こせない」はい嘘
nullで落としてるようなバカって例えばGoogleのChromeチームとかかな? まぁ全人類バカなのでしょうがないね
ポインタ(参照)になぜかnull値を許してしまう欠陥言語でのみnull問題が起きる そうでない普通の言語にとってnull安全は当たり前でありそれを意識することすらない 欠陥言語の存在に対してのみnull安全なる言葉の存在意義がある
>>395 そりゃランタイムやライブラリがバグってたらしゃーないわ
>>396 いや、コンパイルエラーになるからそこでちゃんと直せばいい
まあバカがコンパイルエラーを回避することが目的になって余計ひどいことになる未来もあるけどw
null安全はマジで当たり前すぎてメリットでもなんでもないから nullの話なんてしたくないわ
そもそもnullのある言語でもnull参照で死ぬなんてのは よっぽどのクソコードでテストもしてないときだけだろ
関数の定義からnullableが否かが分かるのがOption<T> のうれしいところと思う 加えて引数や戻り値の所有権が分かるのもRustのうれしいポイントかと
fool proofの話をすると Option<T> でも闇雲に unwrap はできるので考えなしのプログラムだとクラッシュする点は変わらない SEGVじゃなくpanicになるとか、落ちる可能性のある箇所が明示される点でnullよりはマシだが
ほんま、そういうことやな null安全で助かるケースなんてそもそもわずかしかないんだ unwrapだとかゼロ除算だとかいろんなロジックミスで結局は落ちる borrow checkerのおかげでデータ競合が起きない、とからへんが重要なメリットと思う
>>402 > よっぽどのクソコードでテストもしてないときだけだろ
そう言うのがボロボロ転がってますけどw
こちらはNull安全協会です、今なら3,000円お支払い頂くとより安全になり免許証入れまでついてます。 本協会ではNullは許しませんが、DBなどの道路にNullが転がっています。 また外部値など入力が無いことを示すのはResult::Errや特異値:-1やNaNなどで表すものではありませんので クソ設計はやめてください、Option::NoneでNullを示し、ほかの言語と同じく必ずmatchで検査してください。 unwrapもダメです。Null安全協会では皆様に頂いたご声援でド素人が語れてゴリラのマウントのように ウッホウッホホと潤っています。またNull安全語り部Rusterの攻撃性は以上ですので近づかないでください
Null安全性はまともなUXを提供したい場合に生産性を改善する道具 なくても落ちることはほとんどないみたいな視点でしか捉えてないなら価値を理解してない
>>386 GCはメモリーリークおこすし
どこで起こすかが実装によって変わる
GCはゴミなんよ
>>409 鼻から悪魔が出てきたりしても言語仕様を逸脱していないこと
Rustはコンパイルできたら問題は起きないみたいに思ってたけど違うのね これじゃやっぱり初心者に毛が生えたようなのがゴミコード量産するのかな
それはそう たとえPrologを使ってもバグはなくならない でもコンパイラのチェックでなくせる類のバグならなくしたいよね
コンパイルを通すために問題の発生するコードを書くとかも考えられるんじゃねーの そっちのほうが分かりにくいような気がする
>>417 あらゆる問題が起きないかというとそうではない(というかそんなプログラミング言語存在しないと思う)けど
大部分のコードのメモリ安全性がコンパイル時に保証されるのはかなり大きなメリットだと思う
例えばuse-after-freeやバッファオーバーフロー、データ競合なんかは問題が発生してもプログラムかその場でクラッシュするとは限らず、しばらく正しく動くように見えてしまう場合もある
この手の異常の原因特定は難しいので、rustでコンパイルエラーや実行時の問題発生時のpanicなどで即問題箇所が分かるようになっているのはかなり嬉しい
初心者に毛の生えたようなのがゴミコード量産しないようなプログラミング言語ってそもそもどういったものなんだろうか 記述に自由度がなく誰がどう書いても同じになるような言語?
386みるとメモリリークの原因が不明っぽいんだけど 言語処理系にメモリ関連任せられるにしても結局原因不明のバグが残るんじゃ意味ないんでわ
>>424 OS書いてるのに言語処理系にメモリ管理任せられるわけないだろ
自作したメモリアロケータのバグとしか思えんが
>>424 バグの数が0じゃなきゃ意味がないというのは違うのでは
100個バグがあるのと1個しかないのでは開発効率が全然違う
>>409 C++の利点は過去資産
既にバグが枯れた過去資産を活用するのが得策
その他の点ではRustが全て完全に有利
C++でうまくかけないヤツとか構造化の仕方がヘタクソなだけだろ
>>424 そう思うんならそれでいいじゃない
意味ないってことで
>>430 それでいいということを認めるなら、
>>424 にもちゃんと反論しろ
>>428 で、バグが減ったか?まるで変わらんやろ。馬鹿馬鹿しい。
C++の存在意義がゼロになったわけではない C++で作られた過去の莫大なライブラリは今後も併用される C++しか使えない過去のプログラマーの活用のためにC++を用いる案件もしばらくは残る
議論したいならまず相手を選ぼうね ルサンチさんを相手にしても理性的な議論にはならんから
個人的には大規模なC/C++の組み込み開発で散々メモリ破壊系の不具合に泣かされてきたから組み込みでRustを使う流れがきてるのに期待してる 国産RTOSだとKMCのToppersベースのOS、SOLIDが最近Rustに対応し始めた
>>435 メモリ破壊ってそんな起きる?
lock,off,len,remainさえ揃ってたら破壊なんて起きなくね?
>>436 そんなには起きないけど1,2機種に1個ぐらいは難問と言われるような不具合があるかな?
共通してるのは再現性がとても低いかつランダムな領域のメモリを破壊する
でもいざ何週間もかけて仕込み入れて再現されて原因特定するとしょーもない不具合だったりする
それこそRustじゃコンパイル通らないような初歩的な原因だったこともある
静的解析ツールは回してるけどどうしても漏れることはある
嘘くせえwメモリ破壊を理由にRustに期待とか意味わからん MMUがちゃんと設定できてないか、スタック不足でリークしてるだけとか、あるいはスレッド競合に見えるし 比べてる対象がOS前提のRustと、そんなもの無い開発を比べてないか
>>436 同意だな
Cなんて学習の過程でなんぼでもメモリ壊すもんだから
逆説的だけどメモリなんて壊し慣れてるんだよ
どうやって壊してるのかどうやったから壊れたのか
だからだんだん目新しい壊し方が無くなってきてスリルは無くなる
このスレがム板内で一番勢いあるのが笑える C++やRustの本スレより勢いあるやん
>>437 すまん、よく分からんわ…
>>439 分かる
壊し方も調査方法もパターン化してくるし、熟れてくると糞コードセンサーが働いて「この辺じゃね?」って見当つくしな
ログもコアもダンプもないなら難しいけども
本当に調査が難しいのは、並列処理があって競合状態が起きてるときかなあ
ランダムな領域のメモリを破壊が毎回起きて組み込みやってます!キリッ
HaskellとRustはコンパイル出来た時点でバグが無いことを保証される。
HaskellとRustのバグはバグじゃなくて仕様と呼ぶからなw
どうせバカが使ってもRc、RefCellばっかのコードで全く所有権なんて活かせないコードにしかならんよ。
>>447 rustのコンパイラって不等号の向き間違ってますよとか教えてくれるの?
日付比較で不等号の向きで古いファイルが消されるか新しいファイルが消されるか決まることもあるしな ふるい分けファイルの方が日にち稼いでいるからデカいはずだと錯覚するヤツが必ずでてきてデススパイラル撒き散らしたりな
仲介イテレータ君かな 「バグ」という言葉すら独自解釈
でかい釣り針は不都合なものから注意をそらせるために使うもの
>>338 リーナスが例外(パニック含む)を受け入れないから
Rustなら例外機構がそもそも無いし パニックを引き起こさないチェック付きの代替も揃っているからな
SanitizerなしでCやC++書ける人にはRust不要かもね 逆に必要な人はRust使った方が幸せになりそうです
例外機構≠パニックという主張はGoでもあるが無理がある。チェックも近代的な言語ならほぼある
Rustは標準ライブラリの条件付きコンパイルをサポートしてるしそのうちpanic-freeな標準ライブラリも作れるようになるんじゃね。知らんけど
Rustで特別に安全っていうのはあくまでメモリらへんの事なんだよね ダングリングポインタ、データ競合、未初期化の変数を読んでしまう、とかみたいなのは起きない こういうのはC/C++だと巨大プロジェクトではどうしても抜け漏れが出るし、よく脆弱性になるからこれが保証されるだけでもめちゃくちゃ心強い そんで例外っていう危うい仕組みはなくても、他にも気をつけなきゃいけない事はいくらでもある 例えば内部部割り込み、デッドロック、競合状態、メモリリークとかはunsafe使ってなくても普通に起こるので、 プログラマがちゃんと理解して考えて制御しなければいけない
>>445 が明らかに嘘八百なのに、そのことを無視して
>>447 とか
>>453 とか言うのはさすがに無能すぎない?
>>462 445 = 447だし、何いってるかわかんない
>>463 「HaskellとRustはコンパイル出来た時点でバグが無いことを保証される。」
が大嘘ということ。
こんなことを言うのは無能か詐欺師。
誰でも知ってる常識を鬼の首を取ったように言うなよ 見てるほうが恥ずかしくなる
>例外っていう危うい仕組み この捉え方のほうが危うい
>>466 ここで言う例外はプログラミング言語の機能としての例外(大域脱出)のことで一般的な例外処理のことではないのでは
>>435 組み込みでRustを使う流れがきてるのに期待してる
同意
>>467 「一般的な例外処理」の定義をしないで語られても
>>464 お前一人だけこのスレで浮いてるわw
黙っとけ
Rustの勉強も始めたが 驚き感動することが多くてはまりそうだ try/throw/catchがないのに同じことが出来てる仕組みに感動した ?一文字でエラーを上位へ委ねることができたり 単なるenumに過ぎないはずのResult型が巧妙に使えるヤツだったり
>>467 一般的な例外処理で大域脱出でないのがあればそう言えるけど、そんなのあったっけ。
>>472 enumといっても値付きenumだからな
値付きenumとマッチング機構のせいでRustにC++が敗北したとみている
>>476 そのwikiの定義はめちゃくちゃ曖昧だな
回復不能なエラーのことだったり、業務エラーに対するシステムエラーのことだったり
さらには設計で想定されてない問題と言いつつ
ユーザーの入力間違いや他システムと疎通が取れない場合が含まれてたり
>>477 なら例外(処理)の明確な定義ってなんだ?
>>478 話の意図や文脈によっていろんな定義がありえる言葉なんだから
自分の定義を話せばいいじゃん
>>478 まぁ、ここはプログラミング言語を取り扱っているので、各言語ごとの例外機構のことなんじゃないかな
GoやRustなどの言語には例外処理がないと一般的に言われているけど これはtry/throw/catchといった特別な枠組みが存在しないことを意味してる
いやまず
>>477 が定義を示すべきだろw
> そのwikiの定義はめちゃくちゃ曖昧だな
じゃあはっきりしたやつよろしく
いやいや、まず
>>467 が示すべきだろう
示されたWikipediaは曖昧と言うより色々な例外が記載されてるから、この意味での例外と言われてもどれよ?
ってなってるんだから
正確には、例外が発生する「ような」状況、な。 例外すら出さずにpanicするような言語は論外。
元々
>>461 の言う例外とはなんのことかという話で
言語機能としての例外のことを
>>461 は指しているのではないかと推測したのが
>>467 461 は panic による大域脱出の発生を防げたとしても他にも気にすることがある、と言い換えても良いのかと思う
で
>>466 は業務エラーに対するシステムエラーなど他の意味での "例外" (例えばカーネルにおけるメモリ獲得失敗とか) はきちんと取り扱うべきという主張だと思ったので 467 を書いた
変な理解してたらスマン
例外安全性を静的に保証できる言語なんて無かったよな
lowlevel、ハードウェアに近い開発者は例外を嫌う傾向にある
スタック深階層から天元突破する不思議なマホウ エクスセプションナムパトローナ!
try/catchの仕組みはなくても、割り込みの対応はまあどうしても必要だよな?
組み込み用にexception handlerあるみたいよ
言語側に求められる割り込みの対応って何 割り込みの呼び出し規約に従った関数を定義できれば良い?
低レベルの割込み処理に言語側で出来ることはあまり無い コンパイラ側の対応次第 組込みだとマイコンの割込みベクタテーブルに関数(いわゆる割込みハンドラ)のアドレスを設定するだけ ハンドラ内のレジスタバンク切替えやコン テキストスイッチングなどは言語の範疇を超えるのでインラインアセンブラで記述する場合もある
>>494 各関数呼び出し毎にRAIIによるデストラクタ処理が入る
だから例外で一気にスタックを巻き上げるだけにはならない
結局try-catch / throwという特殊な枠組みはRustのように無くしてしまえばいいのかもしれない
>>500 >各関数呼び出し毎にRAIIによるデストラクタ処理が入る
Rustのように戻り値で返す場合も同じでは?
それにスタック巻き戻しを伴わないtry-catch/throwもあるよ
>>500 panic&catch_unwindがあるからrustにtry-catch的な機構はあるんだけど
両者を区別する理由があるからRustにはtry-catchがないと言っている?
それとも try-catch という構文がないことだけを言っている?
>>501 try-catchでも関数からの復帰のようにデストラクタが呼ばれるという話だよ
スタック巻き戻しを伴わない try-catch って panic=abort のこと?
従来の例外は皆がwikipediaの定義を批判しているように何でもかんでも曖昧に整理されずに詰め込みすぎている そして各言語でのtry/catchの使われ方も同様 だからRustでは分離したのではないか? 例えば相手の状態や相手からのデータや入出力次第で起こりうる各種エラーは こちらのプログラムに関係なく起き得ることだから普通に関数の返り値によるエラー処理でよい 一方でそれらとは全く別にプログラムが原因で起きるあってはならない論理的な間違いや もしくはリソース不足などでの続行不可能などの事象はエラー処理ではないためパニック処理として分離した したがって曖昧な存在である例外というものは消え去った
なるほど Goのpanic/recoverは例外機構なのか、っていうとそうじゃない感じするしややこしいなあ
>>503 Rustのpanic って、無かったことにできるようになったの?
Linusがpanic厳禁って言ってたよね?
>>503 カーネルコードではallocできなくても継続不可能とはみなさないように
何を続行不可能な事象とするかはアプリケーションによって変わる
つまりその分け方は業務エラー/システムエラーや回復可能エラー/回復不能エラーなど従来の分け方と同じ
>>506 >>507 そういうカーネルではアロケーション自体も自作だからそこでパニックを発生させずに
例えばシステムコール要求元にENOMEMなどを返すため
>>503 の分離ではエラー処理側に分類される
例外が発生しなければ安全です。 したがって例外をサポートしない言語が安全です。
>>510 なあ、例外がなければ安全だなんて言ってる無能な働き者はお前ぐらいだけど、大丈夫?
>>509 >もしくはリソース不足などでの続行不可能などの事象はエラー処理ではないためパニック処理として分離した
>したがって曖昧な存在である例外というものは消え去った
ここで言ってるパニック処理が例外処理そのもの
例外処理用のハンドリング方法を別途用意しただけであって例外というものが消え去ったわけではない
>>509 カーネルコードでアロケーションエラーを例外としてではなく通常のエラーとして処理するのは
アロケーション自体が自作だからではないよ
Rust坊の植民地になった。ここまでC/C++に対する優位性の証明ゼロ、分裂したRust坊を収容するスレ あんたらが本当に必要なのはRust初心者スレだ。親の仇のようにC/C++に攻撃性を向けるのはもうやめたら?
元々はRustスレに定期的に出没する「俺は天才だからC++でも安全なコードを書ける、Rustの制約はパフォーマンスの足枷」ってうるさい奴を隔離するスレだったんだよな あいつがフェードアウトしたのに逆の意味でスレが機能し続けるのは皮肉なもんだ
>>503 英語版wikiの定義を読むといい
例外の定義や理解1つとっても日本がIT後進国なのを痛感する
>>518 > 日本がIT後進国なのを痛感する
例外の話だけじゃなくてこれはいろんなとこににじみ出てるよな
いろんなwikipediaの記事も日本語版って何かあいまいだったり
説明が簡潔じゃなかったりして驚く
まぁこれに関しては国のIT進歩度というよりは
あっちの人のほうが単に理論的で
理論的に書くのが好きで
理論的に書いてないのを許さない文化がるんだと思う
>>518-519 そういう具体性の欠片もないレスでドヤ顔されても… w
>>519 それが逆に数学分野や工業化学分野だと、日本の方がはるかに端正で正確な記述だと思っているのです…
>>521 まぁ個人の感想なんで気にしないでねw
あとプログラミング言語の本も日本人が書いたものより
海外のものを翻訳したやつのほうがスッキリしてると感じる
説明も体系的というか
www 503 == 520 == 521 www
wikipediaで知識を語る超初心者がマウント取るための厨房すれ
例外をサポートしない言語は例外が発生しないので例外安全です。
型安全性を保証しない言語は型検査エラーを起こさないので型安全ですって言ってるようなもんやん
例外安全てのは例外によって引き起こされる問題に対して安全かどうかなんだからその喩えは不適切
全てのエラーは例外が原因です。 例外サポートを無くしましょう。
>>526 https://en.wikipedia.org/wiki/Exception_safety > The guarantees presented here originated out of work on C++, but apply equally to other languages and error-handling mechanisms.
Rustがtry-catchの例外機構を持たない理由は非常に単純で (A) 本質的にリカバリできることは通常のエラー処理だけで十分に対処可 (B) 本質的にリカバリできないことはpanic 前者の(A)では関数がResult<T,E>で返しそれがエラー時Err(E)の時に 処理をスルーして上位へ移譲したいならfunc()?と?を1文字付加だけで済む仕組み 一方で(B)の「本質的にリカバリできない」panicとは具体的に次のどちらかとなる (1) プログラムに論理的な間違いがある場合 (2) 何らかのリソース不足になった場合 この(1)は具体的に以下のようなケースがある - ありえない状況に陥ってプログラマー自らpanicさせる場合 - 一部の標準ライブラリに対してありえない値を渡した場合 - 配列などで範囲外のインデックスで操作しようとした場合 - ResultやOptionで正常値でない時にunwrap()した場合 - RefCellやRwLockで実行時借用ルールを犯した場合 これらはプログラムに論理的な間違いがある場合のみ生じるためエラー処理とは本質的に異なる 一方で(2)の「何らかのリソース不足になった場合」は プログラム自体には論理的なミスはないが何らかが溢れた以下のケース - 数値型が溢れて計算を続行できない場合 - ヒープが溢れて新たにアロケーションできない場合 - スタックが溢れて新たに関数呼び出しができない場合 このうち数値溢れ演算はpanicを起さないチェック付き演算で置き換えて回避可能 アロケーションもpanicを生じさせないアロケーターを作ることで回避可能 # ちなみに「リカバリできないことはpanic」の考えはクロージャ単位にまで拡張されていて # panic::catch_unwind(クロージャ)を使うとResult<T,E>を返しpanic時にErr(E)を得られるため # そのクロージャ自体は内部でリカバリできないがpanic発生を捕捉すること自体は可能 このようにRustでは曖昧な存在である『例外』を廃して 通常のエラー処理と真の異常時であるpanicの二種類に分けて扱っている
昔のテレビにはホワイトノイズあったけど、そんな感じです
プログラムには二種類ある。 例外か例外でないか。 例外は悪。 それ以外は善。
じゃあ配列の範囲例外が発生するプログラムは全部悪ですね、範囲外を示して書き換えられるようにしないと! なるほどです!ためになります!
>>535 それはプログラムがバグってるから当然悪
正しいプログラムで範囲外アクセスが生じることはない
>>532 数値の溢れをリソース不足に分類するのは違和感あるなあ
論理的間違いに分類するのが適切では
>>537 例えば以下のフィボナッチ数列を表示するプログラム
fn main() {
let mut m: i32 = 1;
let mut n: i32 = 1;
loop {
println!("{}", m);
let next = m + n;
m = n;
n = next;
}
}
これは45回まで正しく表示した後に46回目に数値が溢れてpanicとなる
プログラム自体に論理的な間違いがあるわけではない
ただ数値の溢れというリソース不足を起こしただけにすぎない
配列の範囲外(Index bounds)と言っているのに、数値の溢れ(overflow)をリソース不足と言い出す 「論理的間違い」とか何を言ってるのかサッパリ分からんな、こんすれの隔離Rust超初心者たち…
>>539 その違いは明白
配列の範囲外アクセスはプログラムが論理的にバグっている時のみ生じる
数値の溢れはプログラム自体が論理的に正しくても生じる
>>541 それは単なるリソース不足による数値の溢れだから無意味
例えば
>>538 のプログラムはi32型をi64型やi128型やu128型にすれば少しは延命する
例えばu128型(unsigned 128bit整数)にすれば185個の正しいフィボナッチ数列を出力できる
しかしそこまでに過ぎずこれはリソース不足の問題である
それより上はBigIntなどの数値上の上限がない型を用いることになる
するとこれもいずれ途中でメモリ不足でアロケーションできず同様にpanicするだろう
したがってこれは「プログラムの論理的な間違い」ではなく「数値の溢れというリソース不足の問題」である
>>541 論理的に返答できる相手がどうかも論理的に考慮してくださいよ
有限回のイテレーションしか回せないことが分かっているのに無限ループで書くのはプログラムの論理的な誤りじゃないんだ? メモリだのファイルディスクリプタだのPIDだのの枯渇、いわゆる通常の「リソース不足」と違って、事前に発生が完全に予見できるのに?
一般的に対策としてはもっと大きな整数が扱える型を用いることになり行き着く先はBigInt 例えば以下のフィボナッチ数列を表示するプログラム 論理的な誤りがあると主張するならば具体的にどこをどう直しますか? use num_bigint::BigInt; fn main() { let mut m: BigInt = 1.into(); let mut n: BigInt = 1.into(); loop { println!("{}", m); let next = m + n.clone(); m = n; n = next; } }
>>538 普通は必要とされる範囲を規定してそれに適した型を使う
なのでオーバーフローは論理ミスだよ
>>546 しれっとBigIntに直したそのプログラムには論理的な誤りがあると主張しません
>>538 のi32版は論理的な誤りがあり、+の代わりにchecked_addを使って以下のように修正できます
fn main() {
let mut m: i32 = 1;
let mut n: i32 = 1;
loop {
println!("{}", m);
if let Some(next) = m.checked_add(n) {
m = n;
n = next;
} else {
break;
}
}
}
https://play.rust-lang.org/?version=stable& ;mode=debug&edition=2021&gist=17058fd1c2a1c69f111ac09a94681ee6
>>545 有限回のイテレーションしか回せないとしてもその回数を事前に知るのは困難ではないか?
だから無限ループを用いるとこには何ら問題ないと思う
>>547 範囲を規定できる用途ばかりではないだろう
そのケースは出来る限り多くのフィボナッチ数を出力したいのだから範囲を規定することがナンセンス
>>548 それは
>>532 の「このうち数値溢れ演算はpanicを起さないチェック付き演算で置き換えて回避可能」の通りだから当たり前
>>549 > 範囲を規定できる用途ばかりではないだろう
規定できる用途の方がはるかに多い
て言うかまともなプログラムなら規定してないなんてことはまずない
テストできないし
> そのケースは出来る限り多くのフィボナッチ数を出力したいのだから範囲を規定することがナンセンス
そんなケース滅多にないだろw
>>551 「チェック付き演算に置き換えて回避可能」は「本質的にリカバリできない」に含まれるのか?
ていうかそもそもその区分は何のために存在するんだ?
Rustが例外を採用しない理由として言語開発者たちがそのように主張しているのか?
それとも君の感想?
>>553 前者はpanicを回避可能
それでも計算続行不可能という点では後者の本質的にリカバリできないに該当なのかな
だからそれらは両立していると思うのだがどうだろうか?
あと「例外を採用しない理由」をなぜここで突然言及するのか疑問だが
もし以下の話について言っているのならば
>>532 >> Rustがtry-catchの例外機構を持たない理由は非常に単純で
>> (A) 本質的にリカバリできることは通常のエラー処理だけで十分に対処可
>> (B) 本質的にリカバリできないことはpanic
チェック付き演算を使用した場合は前者になるし
使用せずにオーバーフローすれば後者になるのだから
そこに何か明白でない論点はないと思うのだがどうだろうか?
>>546 それリソース不足にはなるけどオーバーフローにはならないよね?
>>552 ケースが多いか少ないかは関係ない
ケースが少ないから無視していいなんてことはプログラミング界隈ではありえない
>>555 元々こう書かれてるからそこはどちらでも関係ないかもな
多倍長整数型が溢れるのはリソース不足しか思いつかん
>
>>532 > - 数値型が溢れて計算を続行できない場合
今日はNGしやすくて助かる いつもこの調子で頼むよ
>>553 リカバリできないかどうかは状況に応じて開発者が主観的に判断するものなので
「本質的にリカバリできない」かどうかを考えるのは無意味
エラーハンドリングの基本
もちろんRustの言語開発者も同じ考え方
https://doc.rust-lang.org/book/ch09-03-to-panic-or-not-to-panic.html Rustはそこに書いてあるようにエラーをResultで返すかpanicかの2択で済むもんな
>>556 >> - 数値型が溢れて計算を続行できない場合
だからそれは論理間違いだろ
数値型のオーバーフローをリソース不足と言って共感得るのは無理だろうな プログラムにおける上限下限は暗黙的または経験則的に考慮して設計実装されるし、まともなユニットテスト書けば当然検出されるバグ 仮にオープンソースとして世に出すなら、マニュアルやバグレポートに対してどう対処するのか興味ある
曖昧な例外を廃して、とかいっても結局そういう「経験的」とかいう曖昧なレベルでしかなされてないってことよな
結局try catch例外処理なんて最初から不要なものだったんだな だから最近の言語RustやGoにはそのような無駄なものがないわけだ
Rustが例外機構を無くとも同等のことを快適に記述できる要因は二つ HaskellのEitherモナドを値付きenumとして表現したResult<T,E>を関数の戻り型としたこと そしてResultがErrの時に?オペレーターにより見えない即時returnをするショートカットを用意したこと
そういえば例外の信奉者ほどJavaの検査例外を糞味噌に言うけど、例外機構の型検査をきっちりやろうとしたら ああいう方法しかないわけだよね。
フロントエンドやサーバーサイドは間欠故障まではあっても、大抵リトライとタイムアウトで救える バックエンドの耐障害性の設計がまともなら、だけど そりゃエラーチェックなんて馬鹿らしくなるわな
大半のアプリケーションでは個別にハンドリングせず 集約エラーハンドラに任せたいとエラーのほうが圧倒的多数だから 呼び出し階層全てにどの例外が発生しうるかを書いていかないといけない検査例外が嫌われるのは自然なこと Javaの場合は例外クラスの階層の問題とかその他の要素も相まって糞味噌扱い
なるほど こういう理解であってますか? 「Javaの検査例外」と「RustのResult/Optionエラー処理」を比較すると (共通点) 以下をコンパイル時点で強制することで安全性を保証 「誰かがエラー時の捕獲と処理(Javaではcatch、Rustではmatch等)を必ずしていること」 (相違点) Javaでは例外と同じtry-catchを利用 (そのため入れ子で例外が握り潰されたりややこしい) Rustでは例外はなく通常の関数呼び出しと値返し処理となり、 関数の返す型がResultまたはOptionのenum型、 多段呼び出しの場合に途中で「?」使用によりエラー時にスルー可、 自分もしくは上位の誰かがResultまたはOptionのenum値をチェックしてエラー処理 Rustではエラー時にエラー表示して終了で良い場合は以下の楽にサボる方法もサポート 最上位のmain()がResult/Optionを返すことで自動的にエラー時に表示終了 ResultまたはOptionをunwrap()等してエラー時に即時panic終了 このpanic終了はスレッド単位やタスク単位も可能なのでサボりサーバー等も実装可
Rustも呼び出し階層全てでどのエラーが発生しうるか型で管理しないといけないからJavaの検査例外と同じ面倒臭さがある 面倒臭いからといって全部Result<T, Box<dyn Error>>にしちゃうと何のエラーが発生するのか分からなくなってしまう 面倒臭さと堅牢さのトレードオフ
>>572 dyn Error返しでもエラー処理自体は可能なので
Rustは様々なサボり方をサポートしつつ堅牢にすることもできる選択があるので良いと思います
戻り値を返さないコンストラクタやデストラクタ内でエラーが発生したら、例外 以外に通知する方法があるなら教えてほしい。 例外ハンドラを書かないって、エラー処理を一切しない、例えばディスクが一杯で 書き込めないとか、何かあると問答無用で落ちるプログラムってことだぞ。
例外 (panic) 以外ないね エラーが発生しうる処理はデストラクタが呼ばれる前にやるべきかな RustでもBufWriterなんかがスコープアウトでdrop呼び出される前に明示的にflush必要だったりする (drop内のcloseで発生するエラーは無視される)
>>574 I/Oなどエラー発生の可能性が必ずありうるものはRustではResultが返る
唯一の例外がデストラクタすなわちRustではdrop
そこで問題になりうる可能性があるのはRAIIで自動的に呼ばれるデストラクタに依存して処理を行なうケース
エラーを捕捉したい時は
>>575 のように事前回避するがpanicさせてそれを捕捉も可能
>>574 コンストラクタやデストラクタ内ではエラーが発生しないように作れって習わなかった?
それでも避けようのないエラーなら落としたほうがいい
プログラム全体を落としたくなければスレッドやプロセスを落とす
unsafeのpanic-safeはそれなりに気を遣わないといけないよね safeだと特に何も考えなくても良い?
C++は何種類もコンストラクタがあって大変だが Rustはコンストラクタが無いため問題は発生しない Rustにも自動で呼ばれるデストラクタはあるが その前に捕獲すべきエラーが発生しうるものを自分で処理しておくので無問題
俺はコンストラクタで例外投げないし投げさせないな コマンドのような短命プロセスで雑な実装で良いとか、必然性があるなら別だけど
コンストラクタと言ってるからc++だと思うけど事前条件を満たさないでコンストラクタが呼び出されたらどうするの?
>>583 > コマンドのような短命プロセスで雑な実装で良いとか
何その意味不明な必然性w
いやわかるやろ 長期間安定して走らないといけないプログラムとそうでないのとはあるやろ
>>584 ファクトリメソッド経由でしかコンストラクタは呼び出せないようにするんだよ
コンストラクタでエラーが発生しないようにするのはリークの問題じゃなくて使いやすさの問題 new Hoge()を呼べるなら個別にハンドリングが必要なエラーは発生しないと分かるのが重要 デストラクタと違ってコーディング規約的なもの
>>589 コーディング規約(w
コンストラクタ内で、動的配列のクラスやテンプレートを使ってると、例外が発生する
可能性は常にある。 他の言語は知らんが、C++の場合、コンストラクタ内で例外が
発生すると、デストラクタは呼ばれない。
例えば、ファイルハンドルをラップしたファイルクラスがあったとして、引数なしの デフォルトコンストラクタと、引数でオープン済のファイルハンドルを渡すコンスト ラクタを定義したとして、後者のコンストラクタが無効なファイルハンドルを引数 として呼ばれたら、例外をスローするように実装するだろ? 後者のコンストラクタは、dup()で複製したファイルハンドル等を扱う際に必要。
>>591 ファイルハンドルが無効な場合をエラーとして処理すべきならコンストラクタを直接使わせずファクトリー経由にする
panic相当の例外として処理すべきならコンストラクタ使って例外スローでかわまない
>>587 それとコンストラクタで例外発生させないことは関係なくね?
コンストラクタも例外も存在しないRustでは問題自体が生じない
>>591 のケースでもRustでは後者のビルダー関数がResultを返すだけで済む
Rustって、名前の通り錆付いてるようだな。 例外(Exception)がないって、要は
Panicって名前とtry〜catchと互換性のない俺仕様の記述を発明しただけじゃん。
https://news.ycombinator.com/item?id=11370841 https://www.reddit.com/r/rust/comments/bzaxf2/why_rust_doesnt_have_exception_handling/ http://joeduffyblog.com/2016/02/07/the-error-model/ 返す型を限定するのは、C++でもコーディング規約で縛れば済むだけの話だし。
結局、Nullポインタ程度で騒いでいるのは、マニュアルフォーカスのカメラでピンボケ
するとか、マニュアルミッションの車でクラッチ繋ぐのミスると、エンストするって
言ってるのと変わらん気がするナァ。
>>595 開発人数が増えると規約を守らせるコストが大きくなるからね
>>595 panicと例外は全く異なる
議論に立ち入りたいならばせめて最小限の理解をしよう
完成した通常のプログラムにおいてpanicが発生するのはメモリ不足の時のみ
次に、例外はそもそも必要ないことに気付こう
エラーが発生する可能性があるならばエラーを返せばよいだけだ
これでプログラミングにおいて困ることはない
try〜catchの例外機構はそもそも必要のないものだったのだ
>>597 panicが発生したときの制御フローは通常のフローと同じなの?
もし違うのなら、通常フローへの復帰はどうやるの?
>>598 unwindingされてキャッチされるまでスタックが巻き戻るよ
例外と同じ
その点も含めて、少なくとも >597 の「全く異なる」は嘘だね。 後段の「エラーが発生する可能性があるならばエラーを返せばよいだけだ」についても、 じゃぁ何で panic があるの?ってなるし、どういうわけか例外憎しで適当なこと言いたいだけみたい。
rustのpanicとかエラーハンドリングの考え方はgolangの影響大きい気はする Result型を使うか多値でエラーを返すかの違いはあるが、panicという名前と動作、戻り値との使い分けは同じ
なので
>>595 のrustは俺仕様を発明したという指摘も事実と異なると思う
エラーモデルの理解が浅い人を寄ってたかって叩いたところで得るものはないぞ
>>598 panicはバグ発生かメモリ不足でのみ起きる。
だから通常フローへの復帰はせずにabortとなる。
abort前に後処理をしたい時やデバッグ情報を出したい時のためにstd::panic::catch_unwindがある。
それらの処理のためにスタックが巻き戻る。
>>600 一方でtry catch例外処理はpanicとは完全に異なるものである。
単なるエラー処理でも使われて通常フローへの復帰をする。
そのためtry catchが言語の構文となっている言語も多い。
GoやRustにはこの例外処理はなくtry catchも無い。
プログラミングにおいて、エラー処理のためのtry catch例外処理は本来不要なものである。
エラーは関数の戻り値で返せばよい。
このように本来のやり方でエラーを返すのがGoやRustであり、これで実際に動いている。
つまり、単なるエラー処理のための例外機構は必要ないものであることがわかる。
>>604 話が微妙に違うなぁ。
「エラー処理としての例外は不要(panicや例外みたいに制御フローが異なる機能は必要)」
という話と
「例外処理そのものが不要」
という話がごっちゃになっていない?
>>604 > プログラミングにおいて、エラー処理のためのtry catch例外処理は本来不要なものである。 > エラーは関数の戻り値で返せばよい。 あらゆる関数/メソッド呼び出しのたびにエラーチェックをするのが煩雑だから、try-catchが生み出されたんだと思う。 例えば、データベースアクセスが発生する三つの関数を呼び出すとき、 try { foo(); bar(); baz(); commit(); } catch () { rollback(); } みたいな。 続行不能なエラーが発生したが、本流に戻る必要があるときは便利。 >>605 話がごっちゃになっているのはtry catchの例外処理。
Rustでpanicが起きるのはバグとメモリ不足であり、絶対に起きてはいけない状況。
だからpanicの標準動作はそのままabortとなっている。
一方でエラー処理は起き得ることだから関数の戻り値で返す。
一方でtry catchの例外処理は、それらをごっちゃにまとめて扱っている。
単なるエラー処理を、なぜ、try catchで扱ってしまうのか?
それは関数の仕様設計ミスである。
ちゃんとエラーを返せば、単なるエラー処理のための例外処理は不要となる。
Rust擁護するあまり無理筋の論理展開だな プログラミングに必須じゃない機能は不要と言い出したらキリないのでは
>>607 rustのpanicだってabuseできるし
べき論の話で言ったらC++もエラー処理には戻り値を使うべき
現在のベストプラクティスは両者とも大差ないのでは
>>606 Rustなら色々やり方あろうけど、わかりやすい例にするとこうなる。
fn main() {
match sub() {
Ok(result) => { commit(); println!("OK: {}", result); },
Err(err) => { rollback(); println!("ERROR: {}", err); },
}
}
sub() -> Result<DataType, Error> {
let a = foo()?;
let b = bar()?;
baz(a, b)
}
foo(), bar(), baz()各々はResultでエラー値も同時に返しているが、エラーチェックはまとめて出来る。
ResultはOkとErrの2つを取るenumであり、matchは強力なswitch相当と思っていただければいい。
try catchといった例外処理がなくてもプログラミングで困ることはない。
>>609 > べき論の話で言ったらC++もエラー処理には戻り値を使うべき >>606 のコードをこんな感じで書くの? int process() { if (foo() != 0) return -1; if (bar() != 0) return -1; if (baz() != 0) return -1; return 0; } int hoge() { if (begin() != 0) return -1; int ret = porcess(); if (ret == 0) { if (commit() = 0) return 0; } (void)rollback(); return -1; } >>610 > foo(), bar(), baz()各々はResultでエラー値も同時に返しているが、エラーチェックはまとめて出来る。
できないよ。
失敗した段階で処理を中止する必要がある。
あ、ひょっとして「?;」ってエラーが発生したらそこでsub()を抜けるってこと? まあ、だとしても、C++でもエラーチェックベースで実装しろということにはならないけどね
大抵の言語では、例外が発生したらスタックトレースが取れたり、例外オブジェクトそのものにエラー発生場所・エラーコード・エラーメッセージなんかが入ってたりするから、使わない手はないと思うよ
>>611 その場合でも、Rustならば戻り値をResultにしてこのように見やすくプログラミングしやすい。 fn process() -> Result<(), Error> { foo()?; bar()?; baz() } fn hoge() -> Result<(), Error> { begin()?; match process() { Ok(()) => { commit()?; Ok(()) }, Err(err) => { rollback(); Err(err) }, } } >>613 その通り ?オペレータは、ResultがErr(err)の時にreturn Err(err);する。 正確には便利に変換してくれるreturn Err(From::from(err));だが本筋でないので略。 >>615 > ?オペレータは、ResultがErr(err)の時にreturn Err(err);する。
なるほど、勉強になった
ただ、前述したとおり、書き捨てのプログラムでない限りエラーが発生したときには詳細なエラーログを出力する必要もあるし、Rustの常識が多言語でもベストプラクティスとはならないと思うよ
>>614 スタックトレースまで必要になるならば、それはエラーではなくプログラムのバグだろう。
その区別を付けたほうが好ましい。
そして、エラーではなくバグならば前述したようにpanicの対象なのでpanicさせることもできる。
>>616 Resultの正常値もエラー値も任意の情報を持たせられるので必要な時に必要な処理をすれば困ることはない。
>>617 そのGoogleのC++スタイルガイドに「C++の例外は使いません。」と明記されているのか。
これはGoogleが正しい。
もちろん、Googleが作ったGo言語に例外はない。
プログラミングにおいてtry catchの例外機構は不要である。
try/catchよりもRustの方法が良い点としては let val = foo()?; とした時に 正常値valの時だけに専念できるだけでなく foo()はエラーを返すこともあってその処理は上位に委譲していますよ!と ?オペレーターの存在で明瞭になる点 これは裏返せばtry/catch例外方式の致命的な欠点 どこで誰が例外を返すのかわからなかったり 多段呼び出しの途中の関数では例外が通過するのかどうか全てを追わないとわからなかったり プログラミングにおいて例外は悪だと思う グーグルはちゃんとわかっている
>>618 > スタックトレースまで必要になるならば、それはエラーではなくプログラムのバグだろう。
エラーが発生した場所がどこであるのかが例外オブジェクトに含まれているなら、スタックトレースが不要な場合もあるかもしれませんが、あればどういう呼び出しのときにエラーが発生したのかわかるので便利です
> その区別を付けたほうが好ましい。
大抵の場合は例外の種別や例外オブジェクトの継承ツリーで区別をつけてると思います
LogicExeptionを継承する例外ととRuntimeExceptionを継承する例外とか
>
>>617 > そのGoogleのC++スタイルガイドに「C++の例外は使いません。」と明記されているのか。
> これはGoogleが正しい。
Googleがそうやっているだけで、それがベストプラクティスとは限りません
>>611 のコードにエラーログ出力を追加しようとしたらひと苦労です
Googleのスタイルガイドでは、C++の例外は雑に扱えないぐらいには面倒だしメリットがそこまで大きくもない、って書いてるぐらいで、例外は不要だとは断じてないよね 面倒だからGoogleの巨大なレガシーコードには今更例外を導入できないし、それが依存する可能性のあるプロジェクトにも例外は使わせたくない、って感じでしょ
>>620 >>621 だからこそGoogleもMicrosoftもAmazonもFacebookも一緒になって共同でRust Foundationを設立。
それぞれ新規のものや既存のものの改善などを機会に、Rustへの移行を着実に進めている。
既存の枯れたものまで一気に置き換えるという無駄なことはしないが、今後もC++が使われ続けるのはそれだけになる。
>>622 話がずれていってるけど、大本の話題はこれだからね
> プログラミングにおいて、エラー処理のためのtry catch例外処理は本来不要なものである。
> エラーは関数の戻り値で返せばよい。
あと、軽く調べたが、googleはSTLもboostも基本使えないみたいよ
もちろん、例外をthrowするサードパーティ製ライブラリも使えない
修行僧みたいw
あと、Microsoftは違うスタンスみたいだよ
https://docs.microsoft.com/ja-jp/cpp/cpp/errors-and-exception-handling-modern-cpp?view=msvc-170 > 最新の C++ のほとんどのシナリオでは、論理エラーとランタイム エラーの両方を報告および処理する方法として、例外を使用することが推奨されます。 特に、エラーを検出する関数と、エラーを処理するコンテキストを持つ関数の間に複数の関数呼び出しがスタックに含まれている可能性がある場合に当てはまるとします。 例外は、エラーを検出して情報を呼び出し履歴に渡すコードに関する、正しく定義された正式な方法を提供します。
>>624 なるほど
プログラムのバグとエラー(=入出力や相手次第で発生)の両方を、ごっちゃに同じ例外で扱ってる自覚はあるわけだ。
>>615 のRustのように書ければ例外を使わずともエラーを綺麗に明瞭に処理できるのだが、
C++では言語の機能不足のため、修行僧モードになるか例外を使うかの二択なのだろう。
いずれにせよMicrosoftもRustに積極的だから、時間をかけて脱C++へ進んでいることに変わりはない。
>>625 > プログラムのバグとエラー(=入出力や相手次第で発生)の両方を、ごっちゃに同じ例外で扱ってる自覚はあるわけだ。
そもそも、アプリケーションプログラマバグによる例外のthrowはほぼ書かないと思いますけどね
バグ由来の「異常発生」には、ほぼ誰も気にしてないと思うよ(もちろん、最終的な処理が必要なら書くけど)
> いずれにせよMicrosoftもRustに積極的だから、時間をかけて脱C++へ進んでいることに変わりはない。
多分、30年は無理じゃないかな(個人の感想です)
Java, C++がでてきてからもう30年くらい?かな
COBOLやFORTRANの生き残り具合を鑑みるとそう思えます
https://www.tiobe.com/tiobe-index/ Fortran 19位
COBOL 25位
Rust 26位 ← 思ったより検討してた
Rustの利点はわかったけど、?演算子とpanicは例外の発展形にしか見えないなぁ。 (?演算子でエラー移譲を受けた)呼び出し元は、エラーを無視してもpanicしなくて済むのかしらん? エラーを処理しなきゃいけないんだったら例外と大して変わらん気がする。
>>626 単なる通信エラーにすぎなくてもtry catchの例外で受ける例はあるよね。
>>606 のデータベースアクセスの例だと、DBサーバーとの通信時エラーが起きるとfoo()は例外を投げることになる。
しかも例外を投げるのはfoo()自身ではなく、そこから呼ぶDBサーバ通信部分だったり、そこから呼ぶ汎用通信ライブラリだったり、誰が例外を投げるかわからない。
>>627 今書いている関数で例外が発生するのかどうか、奥底まで追わないとはっきりしないデメリットが例外にはある。
?演算子を使えば、下からエラーが来ていて上へエラー処理を移譲していることが明確になる。
あと、質問に対する答えは、main()関数までもがさぼってResultを返せば、自分でエラー処理をせずともエラー表示される。
>>629 実際にはこないのに来るかもしれないと思わせるだけかもしれないだろ
それならtry catchだって来ると思っとけばよい
>>627 エラー処理はそんな大変なことではなく例えば
if let Ok(value) = foo() {
bar(value);
}
と正常値の時だけ処理したりも出来る
正常値を得るにはif letやmatchやその他にResult型のメソッドなどを必ず使わないと正常値を取り出せないので
Rustではエラー値なのにチェック忘れで突き進むバグが生じないのも利点
>>632 EnumであるResult型がとりうる値の種類
パターンマッチさせてResultの中身がOkの場合だけ条件が真になる
>>627 メリットでもデメリットでもあるが例外との一番の違いは
関数の型でどういうエラーが発生するのかしないのか分かるという点
>>570 >大半のアプリケーションでは個別にハンドリングせず
>集約エラーハンドラに任せたいとエラーのほうが圧倒的多数だから
どこでなぜ起きたかわからないエラーをキャッチしてもなぁ。
erlangのlet it crashのようにエラーの種類は考慮しないってんならわからんでもないけど。
>>632 Okはenumの識別子。
Result型はenumでありOk(正常値)とErr(エラー値)のどちらかになる。
enumといってもRustは識別子に付随する値を持つこともできる。
つまりC/C++には無い新たな枠組みで、これがRustを強力にしている一つ。
>>630 try catchは関数呼び出しが多段になった時に、
途中の関数ではtry catchもthrowも出てこないから情報がなく気付けない。
Rustは途中の関数で?オペレータを必ず付けるから、
エラーが起きる可能性があることを必ず認識できる。
>>631 Resultに対して多数のメソッドがあって短くエラー処理できる点もいいね。
例えば以下の2つは同じで、エラー時にDEFAULT_VALUEとなる。
let a = foo().unwrap_or(DEFAULT_VALUE);
let a = if let Ok(value) = foo() { value } else { DEFAULT_VALUE };
以下の2つも同じで、エラー時にクロージャ |err| bar(err) の値となる。
let b = foo().unwrap_or_else(|err| bar(err));
let b = match foo() {
Ok(value) => value,
Err(err) => |err| bar(err),
};
>>588 bad_allocは絶対発生しないシステムなの?
>>635 集約エラーハンドラは汎用のエラー画面表示やログ出力のためだぞ
例外の中身を見ればどこでなぜ起きたかはわかるがユーザーには対処できないものを扱う
Erlangは軽量プロセス単位のリトライなので全然違う
>集約エラーハンドラは汎用のエラー画面表示やログ出力のためだぞ 例外マンセー軍全員こう思ってる? 参ったw
>>631 戻り値無し(副作用目的)で失敗する可能性のある関数もチェック忘れ防げるようになってたっけ?
例外が嫌いすぎて例外使ったことないエアプだから、頓珍漢なことしか言えない 議論する価値ないわ
>>640 正常系の戻り値がない関数なら戻り値はResult<(),Error>になって、これを無視するとwarningが出るから気付く
>>640 まず関数の戻り型はResult<(), Error>となる
()はRustで戻り値なしを意味しタプル0個と覚えれる
次にその関数を普通にfoo();と呼び出すコードを書く
すると「使われていないResult値がある」とコンパイラに警告される
したがってエラー値チェックを忘れていることに気付ける
>>642 おー、ほんとだ。いいね。
https://doc.rust-lang.org/src/core/result.rs.html#71-75 > //! A common problem with using return values to indicate errors is
> //! that it is easy to ignore the return value, thus failing to handle
> //! the error. [`Result`] is annotated with the `#[must_use]` attribute,
> //! which will cause the compiler to issue a warning when a Result
> //! value is ignored. ...
>>629 > 今書いている関数で例外が発生するのかどうか、奥底まで追わないとはっきりしないデメリットが例外にはある。
今書いている関数では、ハンドリングする例外に着目するだけでいいんだが
(何を言ってるのかわからんかもしれんが)
>>639 > 参ったw
何が参ったなのかわからんが、例外オブジェクトがエラーの情報を持っているから汎用処理にできるんだが
Googleのコーディング規約が神だと思ってるみたいだが、発表された当時内容があまりにアレだったので界隈がざわついた記憶がある 組み込み関連は知らんが、それ以外でGoogleのコーディング規約を取り入れてるところはないんじゃないか
参考にしてるのは業務でまともにC++を使ったことがない素人ばかりかもね
>>629 > 今書いている関数で例外が発生するのかどうか、奥底まで追わないとはっきりしないデメリットが例外にはある。
逆にRustだとなんかの理由で奥底の関数がエラーを返すように変更されたらその上の関数全てを変更するってこと?
Rust始めたばかりだからまだよくわかってないが、エラー処理周りのこと調べると、まだまだ迷走中な感じだな
少なくとも初手から言語仕様として完璧なエラー処理構造が入ってたわけではないことがわかった
Rust のエラーまわりの変遷
https://qiita.com/legokichi/items/d4819f7d464c0d2ce2b8 >>649 まず一般的にどの言語であっても奥底の関数の仕様が変更されたらそれを吸収できるところは変更となる
次にエラーが起きない関数が突然にエラーが起きるようにはならないのでそんな仕様変更は起きない
入出力相手があるものは初めからエラーが起きうることがわかるしメモリ上の操作だけであってもsearchやmatchなど成否が起きうるものも最初からわかっている
「そんな仕様変更は起きない」ということはなく、普通にAPIの設計ミスっててやっぱりエラーになる可能性あった、というのはありうる その場合Rustならコンパイルエラーで気付くが、例外だとこれまで例外出さなかった関数が急に出すようになるわけで、なかなか厳しいね
>>651 > まず一般的にどの言語であっても奥底の関数の仕様が変更されたらそれを吸収できるところは変更となる
例外なら途中の関数の変更は不要だよ
> 次にエラーが起きない関数が突然にエラーが起きるようにはならないのでそんな仕様変更は起きない
お前さんの妄想は要らんよ
> 入出力相手があるものは初めからエラーが起きうることがわかるしメモリ上の操作だけであってもsearchやmatchなど成否が起きうるものも最初からわかっている
計算だけしかしない関数が外部に計算させるように変更されたらどうするの?
>>652 > 例外だとこれまで例外出さなかった関数が急に出すようになるわけで、なかなか厳しいね
例外出すように変更したら当然それを受けるように変更するでしょ?
例外なら発生と受けるところの変更だけで済むけど、Rustだと間の関数も全て変更が必要じゃね?
try-catchは素人にはうまく使えないよなあ、とは思う
てかエラー処理全般、本気でやるとしたら世の中でできるやつはかなり限られてる。 GAFAとか含めてもそう。
>>654 自分で変更したとしても、それを使っている箇所を漏れなく変更できるか?という問題もあるし
ましてや依存ライブラリの仕様変更だったらどうするの?という話
誰もがCHANGELOGを正しく書いてくれるわけではないし、見落としだってある
>>654 途中で低位層の仕様が変わるとか有り得ない机上の空論に対して
どこまで何を前提にしていいのか何もかも不明だから誰も何も答えられない
>>657 ああRustだと全部変更必要だけどサボるとコンパイルエラーになるってことか、了解
コールツリー作れれば例外でもチェックできそうな気もする
>>658 >>652 とか俺も例まで書いてあるのに理解できないアリエナイ君は出てこない方が良いかとw
> 計算だけしかしない関数が外部に計算させるように変更されたらどうするの?
>>659 まぁ変更が面倒というのは全くその通り
個人的にはコーナーケースのデバッグコストを事前に払ってるだけだから面倒よりありがたいって思ってるけど、嫌いな人はいるだろうね
面倒というより本質的に途中の関数には関係ないはずなのに修正が必要になると言うのがちょっと嫌かな まあ現状ではmore betterなんだろうけどなんとか洗練されないものかと
>>659 外部サーバーに計算させるよう変更するには
まずその外部のIPアドレスかホスト名かそれらを含むURIなどが新たなパラメタとして引数に入る
途中の関数があるとすれば全て影響を受けるだろう
さらにそのようなことが必要な規模の計算の場合
外部サーバーを使わずとも自分のところでも並列計算をしていたはずである
また計算以外も含めて今どきはマルチスレッド利用が前提とすると
スレッド間の例外は不可もしくは例外を使わず受け渡しをして投げ直すことになる
結局これは例外を使わない場合と同じことをせざるをえなくなる
>>662 > まずその外部のIPアドレスかホスト名かそれらを含むURIなどが新たなパラメタとして引数に入る
クラスとか使ったことないのかな?
> 外部サーバーを使わずとも自分のところでも並列計算をしていたはずである
はずはず君w
もう少し考えてからレスしないと恥の上塗りにしかなってないよ
>>662 計算じゃなく、データベースにクエリー投げるとか普通にあるだろ。 そういう場合、
いちいち関数の引数にIPアドレスやホスト名を渡すのではなく、オブジェクトメンバ
として持たせて、計算メソッドを呼ぶって実装にするのでは?
んで、サーバー応答がない場合だけでなく、IPアドレスやホスト名をセットせずに、
計算メソッドを呼んだりしたら、例外を投げるよな?
>>658 > 途中で低位層の仕様が変わるとか有り得ない机上の空論に対して
> どこまで何を前提にしていいのか何もかも不明だから誰も何も答えられない
やっぱり例外のことわかってないね
自作関数hoge()がサードパーティ製ライブラリの関数foo()を呼び出しているとき、hoge()ではfoo()が送出する例外をどうするかを実装するだけでいい
その後、foo()が更新されfoo()が依存するライブラリが例えばIoErrorをthrowするようになってfoo()はそれに対して何もしないとしても、hoge()は変更する必要がないし知る必要もない
並行並列処理した時点で例外が破綻するのは事実だな 擬似的に例外を伝播させるにしても途中でエラー値渡しが必要 例外を使えば途中は何も考えなくていいはウソだな
そもそも、例えばJavaScriptでnpmパッケージを少しつかうと、数百個のnpmパッケージがインストールされて数千個のthrowが実装されてて、全貌を知るなんて無理んだんだよ そんなこと知らなくても、JavaScriptでアプリコードは書ける
>>666 スレッド内では関数を多段に呼び出すことはないという主張なのかな?
>>663 >>664 計算を与えるものと
サーバー情報を与えるものは
明らかに独立して扱うべきもの
内部で計算するなら前者だけで済む
なるべく依存関係を少なくモノリシックにならないように設計するのが常識
>>664 ホスト名がないとかサーバーが応答しないとか
そんな普通に起こりうることはエラーを返す
>>665 知らなくていいメリットか知りようがないデメリットか
>>668 並列計算スレッドの中で多段に呼ぶのはいいが何をしたいんだ?
ちゃんと頭の中が整理できていないだろw
コードを書いたことあるのかね?
例外がわかってないっつーか プログラミングど素人だったわw
>>654 そうだよ
Tで返してたところをOption<T>で返すように変更が入るとかは普通にある
型で表現できることのメリットの裏返しで
型で表現してるからこそそれに依存してるところは全部変更が必要
誰か書いてたけど検査例外と同じデメリットがある
>>665 これはRustでも同じ
hoge()ではfoo()が返すResult<T, E>のErrorだけ気にすればいいように作る
(正確にはfooを含むmod Fooが定義するErrorのうちfooが返すものだけ気にする)
>>665 JavaScriptについてちゃんとわかっていないようだな
それらは大量にあっても自分のところに飛んで来ないthrowだ
自分のところに飛んでくるthrowはcatchしないとuncaughtExceptionで怒られる
だから下から例外が来るか否かは把握していないといけない
そもそも途中でライブラリの仕様が変わって例外を投げるようになること自体がナンセンスだが
>>667 まずは例外の基本を理解しなさい
ライブラリ群のソースの中に何千個のthrowがあろうが各々のtry-catchで閉じ込められておりその外に対しては一切無関係
関係があるのは自分に向かって来る分のみ
>>670 > 明らかに独立して扱うべきもの
機能が一緒なのに?
君のべき論ならそうなのかも知れないけど、それが一般的というわけではないよね
>>674 そこは了解
まあ単純に上位に渡すだけならIDEで自動で修正とかできそう
>>679 じゃあ並列計算スレッドの中で多段に呼ぶ関数があるとして
どういう仕様変更をせざるをえなくなるのか具体的に答えてみよ
無いと思うけどな
そもそもrustで言うと Result<T, E> の E を変更するのは破壊的変更だから普通は依存crateのエラー型をそのまま外部に見せるようなことはしない
>>681 スレッド内ではシングルスレッドと同じだろ
スレ読み直してこい
>>683 で、並列計算スレッドの中で多段に呼ぶ関数があるとして
具体的にどういう仕様変更をせざるをえなくなるのか早く答えて欲しい
無いと思うけどな
コードの修正が必要になるって話な > 逆にRustだとなんかの理由で奥底の関数がエラーを返すように変更されたらその上の関数全てを変更するってこと?
>>685 エラーに限らず一般的によくあることだね
返すべき値が増えたり
返すべき型が変わったり
あるいは逆に
引き渡す値が増えたり
引き渡す型が変わったり
それらは機能追加変更でも起きるけど
リファクタリングでも起きたりしてる
Rustでも他の言語でもその状況は変わらない
話の流れ見えてる? > 例外なら発生と受けるところの変更だけで済むけど、Rustだと間の関数も全て変更が必要じゃね? > 面倒というより本質的に途中の関数には関係ないはずなのに修正が必要になると言うのがちょっと嫌かな
>>686 それがコールツリーを遡って何層にも伝播していくのは普通にある事ではない
あるなら設計が悪い
どこでどういう例外が発生するか全部把握している人にとっては造作もないこと
>>687 Rustでも下位でエラー(例外)の種類が増えたとしたら
同じように上位の関数でそれらのエラーを処理する場合
?オペレーターで飛ばす途中の関数はそのまま変更ないよ
>>690 少し上のレスくらいは読んでくれ…
> 逆にRustだとなんかの理由で奥底の関数がエラーを返すように変更されたらその上の関数全てを変更するってこと?
>?オペレーターで飛ばす途中の関数はそのまま変更ないよ ?オペレーターかどうかは関係ないやろ いつもいつもホントいい加減な事言うよなぁ
>>691 その関数の元の戻り型と変更後の戻り型次第じゃないかな
元々がそのエラーと別の他のエラーを返しているか何らかの理由でResultならば
既にその関数呼び出しに?オペレーターを付けてあるので変更なし
その関数の元の戻り型が新たにResultになったのならば
その関数呼び出しに?オペレーターを付ける
それに応じて自分自身に対しても以下同様
>>692 間違ったことは言っていないつもりだが
もし何かミスがあれば指摘くれるとうれしい
もうそろそろ寝室へ移動するが
検査例外の不便さを軽減しつつ例外が送出されることのみ型で明記する方式をとったのがSwift RustのResultを返す方式と基本思想は同じだがエラーの型を明記しなくていいので使いやすい
エラーの種類を型で区別するというのがそもそも無理があったんだろうな。
>>694 エラーの型の明記自体は必要なことだから問題ないんじゃないかな
>>695 もちろんRustではdyn Errorで何でも楽する形から個別に用意して堅牢にする方法まで様々な形態を取ることができる
>>693 > その関数呼び出しに?オペレーターを付ける
> それに応じて自分自身に対しても以下同様
だからそれが必要だろって話
てか、話がループしてるからはよ寝ろ
>>697 型が変わるケースのみ最小限の限定した対応が必要となるのは当たり前
そんな常識を「必要だろ」とわざわざ言われても…
おやすみ
言語が違うんだからやり方や考え方が違うというのはべつにどうでもよくて どちらの方がバグを生みにくいのかが気になる エラーハンドリングにまつわるバグもいろいろあるけど、例えばリカバリ可能なエラーを取り逃してプログラムがクラッシュする可能性が低いのはどっちなの?
メモリがないとパニックしてabortってなんなの? 動作変えられないの?
>>699 それならばRustが安全
Rustのenum Result型から正常値を取り出すには
matchやif letもしくはResult型のメソッドunwrap_*()などの
エラー値ではない時のみ正常値を取り出し使える手段を必ず経る必要がある
つまり正常値を使って処理していくコードはエラー値ではない時だけしか動作しないことが保証される
>>698 常識と言いながら話をループさせるのはもしかして認知症… w
>>701 エラーケースのリカバリの話をしているんだが
>>701 例外でも保証されるじゃん
何言ってんの
ここはrustをよく知らない人に rust初心者がrustをゴリ押しするスレです。
できるだけコンパイル時にチェックしてくれるほうが良い。
>>699 JavaやSwiftみたいに検査例外があるやつはRustと大差ないだろうね
非検査例外しかないやつだとcatch忘れるのを防げないが
あとはfinallyやdeferによるエラー時の後始末は忘れる可能性があるが、RustならRAIIに任せられる範囲内でなら忘れない
>>708 C++との比較だとRAIIは同等だが検査例外がない分Rustの方が有利ということか
>>710 そういうことやね
あとはそのメリットと
> その関数呼び出しに?オペレーターを付ける
> それに応じて自分自身に対しても以下同様
をしないといけない面倒さのトレードオフかと
そういや、Rustの?演算子の性能コストはどうなの? プログラマの負担を増やしても行儀正しいコードを強制しようとするRustが?演算子による明記を選んだのはなんとなくわかるけど、性能コストがどうなるかは気になるところ。 性能調査結果とかある?
>>708 エラーハンドリング方式の違いによる有意な差なんてないよ
それ以外の要因のほうが大きすぎるから
>>712 単に戻り値を返すだけだから
戻り値方式と例外方式の性能比較を参考にすればいい
setjmp/longjmp系と違ってSwiftみたいにResultに展開されるのもあるから コードの見た目と性能は必ずしもリンクしない
>>712 Rustの?演算子による即returnと
C++の例外によるスタック巻き戻しの性能は同じ
どちらもRAIIだから通過する各関数の各ローカル変数に対するデストラクタが全て呼ばれる
>>715 C++の例外は上述のようにデストラクタ処理があるため単なるlongjmpとは異なる
あとヒープがメモリ解放されるためにはunique_ptrとshared_ptrを用いることが必須
>>716 > あとヒープがメモリ解放されるためにはunique_ptrとshared_ptrを用いることが必須
必須じゃないだろ
デストラクタで解放すればいいだけ
まあちゃんとやるには色々面倒ではあるが
>>717 もちろん自分で毎回漏れなく面倒を忘れず頑張るならばその通り
そのコストは見合わないから
単なるポインタ使用ではダメという意味でunique_ptrとshared_ptrを用いることが必須と書いた
>>716 >Rustの?演算子による即returnと
>C++の例外によるスタック巻き戻しの性能は同じ
全然違うよ
コンパイル時の設定にもよるが
一般的には例外が投げられないケースに最適化するから
例外が投げられた時は桁違いに遅い
>>719 桁違いは言い過ぎでは
数割とかじゃないの
例外が投げられなくても try/catchの記述をしただけでコストが余分にかかる
>>719 どっちかって言うと例外にならないケースのオーバーヘッドの方が知りたい
>>723 例外が発生するしないに関わらず
例外が発生した時のために必ず準備をしておくのでその分のオーバーヘッドがある
>>724 あるのはわかってるよ
rustとC++のどっちがでかいかって話で
議論を見てるとC++に落ちこぼれたヤツがRust派に立って復讐劇を繰り広げてるかのようだな
>>722 ,724
そのタイプの実装は廃れて、今はコンパイル時にテーブル用意して「準備」を済ませる実装が主流だと
思ってるんだけど、その「コスト」「オーバーヘッド」って何見て言ってるの?昔の記憶?
c++も言語仕様マウント馬鹿でクソ化した言語の一つだが、rustは確実にその跡を継いでる。
まあRustは、ほぼC++の真似で一部を独自仕様にしてるから。 糞な部分を受け継いでる事もあるだろう。
Firefoxの評判を見れば、Rust製アプリがどういうモノかわかる。 Google Playでコメントを見れば良い。
所詮LLVM言語、FirefoxのエンジンがWebkitに勝てない時点でUnixのコマンドでも書いてなさいってこった
コンパイル出来た時点でバグが無いことを保証される。 したがって、落ちるのはバグでなく仕様。 いまどき落ちるブラウザなんてありえないし。
>>725 Rustのエラー返しのコストは
C++のエラー返しのコストと同じ
C++の例外が最もコストが高い
>>734 正常フローの効率を考えるとそうとも言い切れんだろう。
>>734 だ・か・ら
> どっちかって言うと例外にならないケースのオーバーヘッドの方が知りたい
に答えなよ
C++もRustやSwiftを真似する方向性なんじゃないの?
VIDEO これは例外のほうがコストがかかる。 だからC++においても何でも例外を使うということはなく、 普通にエラーを関数の返り値として返している。
そういえばRustってメモリ不足補足出来なかったけど、あの時のFirefoxってメモリ不足したらどうしてたんだろ
>>739 何を言いたいのか意味不明だが
補足が捕捉ならばメモリ確保(reserve)はエラーを返すので捕捉できる
fn main() {
let len = 1_000_000_000_000;
let mut v = Vec::<usize>::new();
if let Err(e) = v.try_reserve(len) {
println!("ERROR: {}", e);
return;
}
(0..len).for_each(|i| v.push(i));
}
linux限定の話かもしれないけど他の言語ってcopy on writeとかoom killerとかあってもメモリ不足捕捉できる?
>>740 これ最近出来た機能じゃない?
これがなかった頃はどうすんだろって
>>741 oom killerはSIGKILL送られてくるから言語関係なくプロセス側でできることは何もない
linuxだとデフォルトでオーバーコミットされるからユーザー空間のプロセスでメモリ不足時になんかするのは難しいんじゃないの
バリバリのプログラマーとか元より マウス操作の超上手い(自称)理系とか別に嫌いじゃないけどね
コンパイルできた時点でバグがないことが保証されるのに、rust 本体がbugfixされるのはなぜでしょう
>>749 キチガイアンチが「コンパイルできた時点でバグがないことが保証される」と誰もがガセとわかることを連呼する理由は
「コンパイルできた時点で様々な安全性が保証される」という現実が羨ましくて逆恨みでその事実から目を背けたいから?
>>749 ちょっといってる意味がわかりませんねぇ
落ち着いて書込みしましょう
>>751 あ、俺もアンカー消す方マチガエテ、意味不明になったわw
>>744 先週ニュースになったFirefoxの件は
QUIC利用のHTTP/3実装の問題がクラウドプロバイダー側での設定変更で発動して接続障害が起きただけ
当然プログラミング言語とは全く関係なく既に修正された
>>749 なぜ「コンパイルできた時点でバグがないことが保証される」と思ったのですか?
まだまだ枯れてないので致命的バグがあるようですね 仕事じゃ使いたくない
>>755 致命的バグとは何ですか?
C++にもRustにもそんな話は聞いたことがないのですが
>>756 聞いたことないって、聞こうとしてないの間違いでしょ
1.52.1でも致命的バグがfixされたし
C++は今後も仕様拡張を続けるから枯れることはない GCCも毎回大量のバグリストを抱えている
Firefoxはサイトによって落ちるから見れないサイトがある。 アマゾンもどうしても見れないページがある。 不便。
C++とRustのプログラミング言語のスレで なぜブラウザやサイトのページの話をする人がいるんですか?
>>758 君の所では仕事にRust を使えるかもしれないが、うちじゃ使えない、それだけの話
なぜなら枯れてないから
>>761 興味本位の質問だけど、どのC++言語仕様とコンパイラはどのバージョン使ってるの?
どれくらい古ければ枯れてると見なしてるのかが気になる
>>765 > どれくらい古ければ枯れてると見なしてるのかが気になる
枯れてなければ(リリース日が古くなければ)利用しないということではないよ
様々な状況を勘案して利用するものを決定する
ただし、いわゆる「メインストリーム」から外れているものについては、枯れているかどうかはかなり重要
ちなみに、うちではRHEL系のOSを使っていて、基本はそれに付属しているデフォルトバージョンを使う
今だと、gcc 8.5.0
ただし、Linuxだとサードパーティ製ライブラリ等をコードからビルドする必要がある場合があり、そのときは8よりも新しいものも使う
使えるのは、公式がリリースされているバージョン9系のパッケージと10系のパッケージ
また、プロジェクト毎にチームの合意があれば、はじめから9系あるいは10系を使うこともできる
(といっても、プロダクトコードをC++で記述するケースはかなり減ってはいる)
Firefoxはもちろん、LinuxやAndroid OSでもすでに採用されているのに、 いつになったらメインストリームといえるようになるの? さすがにレガシープロジェクトの言語が置き換わるなんて無理だろうし
ちなみに、Rustも全く使えないわけではなくて、許可されれば周辺ツール作成レベルなら使える場合もある なお、RHEL 8系のRustのデフォルトパッケージのバージョンは、1.54.0まで来ている(インクリメンタルコンパイルがデフォルトで有効になったバージョン)
>>767 イメージでしか語れないが、Go言語レベルくらいになれば、メインとして使っても良いというところが増えると思う
なるほど でも、そもそもこんな低レベル向けな言語は、ウェブ開発用の言語ほど使われないだろなあ 組み込みはそのうち使われるようになるだろうけど、 ゲーム開発とかでも使われるようになるのかな?
>>767 そうそう、
> Firefoxはもちろん、LinuxやAndroid OSでもすでに採用されている
ということができるのは、コンパイラのバグを見つけたら自分で修正してPR投げられるほどの優秀な人材が揃っていて、なおかつ工数を潤沢に取れるから
凡人チームがメインで採用できるようになるには、もう少し時間が必要だと思うよ
ウェブ用言語とは思わないけど、一時期のRubyのようにウェブの用途でめっちゃ使われてると思ってる Goが本当に得意なのは、並列処理の実装だろうけど
>>774 並列処理が楽に書けるのは書けるんだけど
データ競合バグもカジュアルに入れ込んでしまう…
Rustみたいなコンパイル時のデータ競合検出はGoにこそ欲しかった
Goはコンパイル時にあれこれ頑張る言語ではないからこそ実現できてる使い心地もあるんじゃないかね
総合すると、RustとRubyがお勧めって事かな。
C++は20年かかってやっと例外の実装が間違いだと認めて方向転換しようとしてる
>>767 "MAIN"streamなんだから、近くにデカい言語があるようじゃ無理だろ。
Perlに対してpythonくらいの関係にならないと。
>>777 Goの-raceは実行時の競合検出だからオーバーヘッドで重いし余分にメモリも喰うし
実際に競合する実行状況にならないとレアケースはいつまでも検出できない欠陥
つまりGoはC++と同じ状況
>>786 race付きでコンパイルしたものは本番で使わないよ
重くて本番で使わない結果 本番環境で運用中に生じる競合を検出できない
>>787 そりゃそうなんだけど実際検出したいバグは本番環境で長時間実行したらたまに出る、みたいなやつなので
手元でrace付けて簡単に再現するやつはそもそもそんなにデバッグにも苦労しないし、いまいち噛み合ってない感はあるなぁ
>>783 例外と例外指定の違いもつかないでC++批判か
>>776 自動でのチェックはできないかもしれないけどgoroutine間で変数を共有しないよう
注意するなら目視チェックでも十分だと思うがなぁ。
>>791 横からレスするけど、並列処理をガツガツ書く機会って少ないから
ちゃんとわからずに書く人多すぎんだよ・・・
やっぱRustみたいなコンパイル時に厳しくチェックしてくれる言語って重要だと思う
>>791 目視で99%見つけても1%残ったら落ちるからなぁ
多人数開発してて差分でレビューしてるときに全部発見できるかというと…できるか?
>>776 のようにカジュアルに発生するってのは問題だが1%見逃すのは仕方ないんでないの?
並列処理のデータ競合バグを100%排除できる言語なんてある?
>>794 少なくともRustはコンパイラやunsafe絡みのバグを除けば原理的には100%なんだから、それと同じくらいまでは頑張って欲しい
せっかくgoroutineが使いやすいのに、目視レビュー頑張ってって言われるとちょっと…
例えばCでグローバル変数絡みのバグを防ぐためにグローバル変数使用禁止という規約はよくあるが それを守るには目視チェックでも十分。そのくらいの感覚。
みんな理解していると思うが念のため Rustコンパイラが100%保証するのは「データ競合(data races)」が起きないこと だからその点ではC++やGoよりは遥かに優れている 一方でデータ競合を除く「競合状態(race conditions)」を100%検出する方法は存在しない だからデッドロックなどはRustコンパイラでも当然ながら検出できない もちろんデッドロックはロック順序決めで対応できるし Rustならロック解除し忘れ防止も大丈夫といったように別の解決方法となる
>>788 テストしないのかな?
それともテストで検知できないような設計しちゃってるのかな?
>>799 C++の従来の例外の諸問題を解決するため
オーバーヘッドが無く決定的な例外(zero-overhead deteministic exceptions)が提案されていてそれを静的例外と呼ぶわけね
その静的例外はexpected<T,E>みたいな感じで関数の返り値として返すわけか
そのexpected<T,E>はRustのResult<T,E>とほぼ同じで別途P0323R10としてstd::expectedへ向けて進行中のようだ
従来の例外メカニズムよりも様々な面で優れているという点は共通認識なのね
>>791 いつもお前がチェックしてるの?
それともお前のチームのあいつもチェックするの?あいつに任せて大丈夫?
>>801 テストでカバレッジ100%とか目指しちゃってる?
テスト終わるのかな?
(真面目な話、長期運用中のレアなバグをテストで捕捉できるんなら誰も苦労しない)
>>805 まぁ、C0カバレッジはおろかC1カバレッジ100%にしても、競合のバグは発見できないことが多々あるんだけどね
テストで競合のバグ網羅的に検出する方法教えてほしいわ...
>>805 データ競合確認用のテストを書くんだぞ
カバレッジ上げて検出できるようお祈りしてるだけじゃそりゃ無理よ
>>808 え?データ競合を網羅的にチェックできるテスト手法があるの?
こんなとこに書いてる場合じゃなくて、学会発表とか特許出願したほうがいいんじゃない?
・複数人で開発している ・その中にど素人が紛れている ・誰でもアクセスできる場所にデータが置かれている というときにど素人がデータ競合をやらかす可能性があるが、それ以外は設計で防げる気がするがどうか
>>810 網羅的なんて書いてないだろ
お前は網羅的にできないから全くやらないのか?
結局の所、高頻度・ロングランテストするくらいしか検出方法ないんですかね
ロングランテストwww 何の関係があるんだよw いつもの知ったかさんでしょコレ
設計自体のバグもあり得るしねえ 形式手法を使うくらいか?
>>814 通常のテストで検知が難しいバグを見つける手段として、高負荷・高頻度・長時間(の組み合わせ)のテストをするのは常識
もちろん、それで問題が発生しなかったからといって、バグがないことが証明されたわけではないけどね
>>792 意地悪なこと言ってスマンけど
「ガツガツ書く」「少ない」
「ちゃんとわからず」「多すぎ」
夢見がちで可愛い表現だなw
井戸の中のカエルが反り返って演説してる気迫を感じる
結局のところ未熟者が書いたコードは当てにならないと言うのがすべて
未熟者に限らず自分自身含む人が書いたコードはまず疑った方が良い
ロングランテストの所有権を複製して仲介イテレータで処理すれば算数は100点!!
RustはFirefoxがまともに動くようになってからでイイわ。 本家すら使いこなせてないのに俺ら雑魚にはまだ無理だわ。
>>824 ブラウザがこのスレにどういう関係が??
>>811 並行性テストすら知らないど素人さんが言うと説得力あるね〜
今はRustで書けばコンパイラがデータ競合も指摘してくれるので大丈夫 C++は既存システムのメンテ用
データ競合起こすようなコードしか書けない奴はプログラマに向いてないわ
ベテランでもデータ競合やメモリ安全のうっかりミスがあることは何度も示されている それらをコンパイラでチェックできる高機能なプログラミング言語が登場したのだから 高機能な新しいものに付いて来れないプログラマこそ向いていない
Cで書かれているLinux OSが あれほどC++は無意味な言語と採用を拒否し続けてきたにも関わらず Rustを一部採用し始めたのが典型的ですね
以前のHaskellのような勢いがあるけど、まったく使われないのもHaskellと同じでは?
うっかりミスで競合バグやメモリ破壊が起きるとは思えんな データ構造やテーブルの設計ができない、メモリ安全な書き方知らないってスキルや知識、経験の問題だろうよ マルチスレッドの使いどころを知らないやつ、知ったか、コミュ障あたりがプロジェクトに混じると起きる そういった猿を炙り出せるrustはパラドックスを抱えてる気もするが俺は好意的
>>830 お前あんの?
俺一回もないけど
どんだけひどいコードかいてんだよw
俺もそうだったが、初めてマルチタスクOSでプログラミングし始めた頃に 興味を持ちやすいのが、マルチスレッドや、メッセージパッシング、 同期、非同期、排他処理など。 そして、実際にプログラム経験を積むにつれ、そういったものは、そんなに 使用しなくてもほとんどのプログラムには関係無いことが分かってくる。 というのは、シングルスレッドでも処理速度が足りる場合が多いからだ。 また、ブラウザ以外では async, awaitなどを使う理由は皆無である ことも分かってくる。複雑になるだけで速度も上がらないから。 ほぼブラウザ上アプリ専用だと考えて良いだろう。
>>837 ウェブ周りは間違った設計が堂々としてて凄い貫禄と思う。
無印ペンティアム辺りの時代を未だに引きずっているのかも。
>>838 貫禄が在りすぎて我々にはどうしようもない。
>>837 色々とおかしいぜ
まずシングルスレッドでも可能な並行処理とマルチスレッドとなる並列処理の違いがわかっていない?
さらに非同期処理と並行並列処理の違いも分かっていない?
まずシングルスレッド内でもマルチタスクで並行処理はするしasync/awaitは用いる
ブラウザ上での各ページのJavaScriptもシングルスレッドで動いていてasync/awaitが使われる
非同期であればasync/awaitは使われるのだからマルチスレッドである必要はない
さらにasync/awaitを使おうと使わまいと非同期処理は必須
ネット通信にしてもI/O読み書きにしても同期かつ並行並列もなく待ちぼうけプログラミングでもしているのかね?
>>837 マルチスレッドは処理速度だけじゃなく、プログラムをシンプルにする目的でも使うんよ
>>841 "ロングランテスト"でしかテストできないという意味では全部一緒ですねw
デスクトップアプリでsureddo使わないと、処理中はアプリが固まるんだけどなw
>>835 お前が無くてもチームの誰かがあったらダメじゃねーの?
>>845 シュアード・ドゥ使わなくてもオルニチン使えば大丈夫..
>>846 データ競合に関しては、ありがたみがわからないんだよね
そもそもそれが発生する設計しないというか...
同感だわ ポインタほどプログラム全体に散らばるようなものじゃないからな
自分で書くぶんにはデータ競合はほぼ踏まないと思ってるし 実際Rustで書いてもSend/Syncエラーになったりはしないんだが だからといって社内の謎ライブラリやらマイナーなOSSが 同程度に信頼できるわけではないからな チェックがあるに越したことはない
>>850 あ、そっか
スレッドセーフじゃないAPIを不用意に使って、共有するなにかが壊れる系のバグはあるわな
データ競合やメモリ安全のコンパイラによる保証よりも Rustは様々な点でC/C++よりプログラミングしやすいことが一番の大きな点だと思う 挙げだすとキリがないけど値格納付enumや強力なマッチング&デストラクチャリングなど含め基本的なことを始めにね 言語にそんな色んな機能は要らないしコンパイラによる保証も自分でやるから要らないという人にはC言語がある C++は何もかもが中途半端な存在となってしまっていることに気付いた
>>858 そもそも苦痛かどうか聞いてるんだけど?
プログラミング言語として優劣差が明白にあります C++とRustの両方を書ける人たちが新たなプロジェクトをする場合 100%Rustが採用されます
kerneldeveloperだけど、c使うな言われたらrust使うかな
>>859 ケースバイケースでしょ
何アホな質問してんだか
>>853 苦痛だが、合わせざるを得ないのが現実だろ
こういうのが嫌なんだよな > Rustのデータベース系クレートでは、長らくORMのdieselがデファクトスタンダードとして各入門系テキスト/書籍でも扱われていましたが、ここ最近はdieselの名前を見かけることはあまり多くないように思います。
C++の線形代数系ライブラリでは、長らくEigenがデファクトスタンダードとして扱われていましたが、ここ最近はEigenの名前を見かけることはあまり多くないように思います。
>>866 標準でないライブラリはどの言語でも一緒やん。
毎年決定版のライブラリやフレームワークが 変わるJS/TSで仕事回ってるし
ブラウザは特殊。 デスクトップアプリでasync,awaitは不要。
もともと並列処理は、スーパーコンピューターで、クロック数の増加速度に陰りが 見え始めた時、複数のCPUで処理することで高速処理をするために発明されたもの。 プログラミングがとても難しいことが知られており、速度が十分な場合は不要。 1コア(スレッド)なのに非同期にする理由は無い。
並列処理は、プログラムの難しさと引き換えに、速くなるためだけに発明された だけの苦肉の策。 技術的な頭打ちをなんとか凌ぐために登場した。 シングルスレッドだと全く速くならないのに、プログラムを難しくするだけで 意味が無い。
>>870 ほー、じゃ直近3年でプロジェクトに採用したFWを時系列に並べてみ?
お前はまずマルチスレッドとマルチコア(or プロセッサ)の違いを理解してから書き込め スパコンの前からマルチタスクは普通に使われてた
>>877 それはアプリケーションレベルでの話で、マルチプロセス。
複数のCPUや複数のコアが搭載されるようになってからのみ、
マルチスレッドプログラミングの意味が出た。
>>877 マルチタスク(マルチプロセス)は、OSの利便性のために生まれた。
速度とは関係無いし、アプリのプログラミングにもほぼ関係無い。
何言ってるんだ? 古くからマルチプロセスで高速化なんていくらでもあるだろ make -j オプションとか知らんのかよ
>>880 シングルコア、シングルCPUのPC-9801だと基本的に速くならん。
>>881 お前CPU Bound / IO Boundって知らんだろ
そんな知識で語るなよw
>>871 最近はブラウザベースのデスクトップアプリ多いよね
>>882 プログラマにあなたのような頭が悪い人が増えているから、
async,awaitが有名になっているのかも。
>>884 もうそういうレスしか返せないならやめたら?
痛々しいぞ
頭が悪い人は出入り禁止にして欲しい。 馬鹿とカシコがごちゃまぜになって紛糾してしまうのが匿名性掲示板の限界。
>>882 でもお前もインフライトキュー知らねーじゃん
>>871 デスクトップアプリでasync,awaitは不要、というのは古い環境だな
非同期を使わずに済むように制限があり
自分でI/O通信アクセスなどするのを許さないか
あるいは同期ブロックされて自分のスレッドは止まってしまう
つまりその場合でも意識はせずともその環境はマルチスレッドを使っている
>>873 1コア(スレッド)なのに非同期にする理由は無い、は間違ってるな
むしろ1スレッドで効率よく色んなことをするために非同期がある
JavaScriptがシングルスレッドなのに非同期を活用しまくりなことを知らないのだろうか?
書き込み内容ではなく、
>>884 のように人格攻撃しかしないのはクソオブオソだから、普通に無視しとけ
>>884 みたいなの釣りなのかマジモンなのかどっちなんだろ
JSがHTMLを補助するために独特の仕組みを生み出しただけなのに、 それを一般化する人が増えて困る。
このスレによく書き込む奴の中に、アスペが一人か二人いるようだ
JSはプログラミング言語として特殊すぎるから、それを基準にしてはいけない。 特にasync,await,PromiseはHTMLの特殊性からきているものなので、 「新しい概念だから他のプログラミング言語にも広めていくべき」 などという見方は間違っている。
async await最初に導入したのってC#では
>>890 論破されて引っ込みつかなくなってからの人格攻撃でしょ
無能によくあるパターン
そもそもマルチスレッド(タスク)や非同期処理はIO多重化への対処であってコアの数は関係無い。 (マルチコアのほうがより効率に処理できるが) 本質わかってないやつ多すぎ。
>>897 > 本質わかってないやつ多すぎ。
お前が一番わかってないだろ…
あと釣り宣言来ましたので今回はこれでお開きのようです
>>897 それはOSレベルで工夫すればなんとでもなるので、マルチスレッドは必須ではない。
ところが、高速化に関しては、クロック数が頭打ちになってきているので、
マルチコア/マルチCPU化して、マルチスレッド・プログラミングで対処する
しかないことが出てきた。
したがって、あなたの主張は完全なる間違い。
実際は正反対。
>>897 の「マルチスレッド(タスク)や非同期処理はIO多重化への対処」のI/O多重化は当然通信も含むんじゃないか
>>901 OSレベルで工夫すればなんとでもなる、なんて無理
通信相手が返事を返すのに数msec、数秒、数分ということは現実に有り得る
シングルスレッドで同期のみならその間は何も出来ない
マルチスレッドであっても通信相手が多数ならば多数のスレッドが必要となりそれらが同期のみなら全て待ちのために停止
マルチプロセスにしても同様でいずれも無駄にOSリソースを使うだけとなる
つまり非同期プログラミングは必須
非同期ならばシングルスレッドでも並行(concurrent)に処理することができる
さらにマルチコアを有効活用するためにマルチスレッドで非同期にすれば並列(pararell)にも処理することが出来る
>>902 > シングルスレッドで同期のみならその間は何も出来ない
Polling って知ってるか?
>>903 select/kqueue/epollなどでポーリングして切り替えながらノンブロッキングで複数I/Oアクセスをする大昔から行われている方法のことだよな
これを同期プログラミングとは呼ばないな
むしろこのポーリング方式で切り替えながら呼び出すコールバック先を単なる関数だけからコルーチン対応にしたものが非同期プログラミングと呼ばれるくらいだ
そしてポーリング状態およびタイマー状態に応じて呼び出すコルーチンを切り替えていくのがスケジューラ
もちろん通常の非同期プログラミングではその部分はライブラリなどに任せてしまい呼び出されるコルーチン部分をプログラミングすることになる
while(kbhit() == 0){ ... } みたいなのを非同期処理って言うのか?
kbhitの中でキー入力を待ち合わせるわけじゃないから非同期処理でいいんじゃね?
>>902 お前は、ゲームのキャラそれぞれが別スレッドで動かされていると
思ってるだろ。
昔からキャラは複数のハードで処理されていると思う人が後を経たなかった。
非同期I/OとノンブロッキングI/Oの違いを述べよ
相変わらず隔離対象のお二人さんは自分の狭い知識と観点が全てなのな アプローチは違うが考え方も知識レベルも似たもの同士 だから反発し合う
もう何を話しているかなんてどうでもよくて、相手が屈服するまで続けるという不毛地帯
>>904 9割方その通りですが
epollやselectなどのポーリング結果で呼び出される対象は単なるコールバック関数でも非同期プログラミングですよ
例えばJavaScriptでは非同期関数のコールバックは単なる関数でよいです
もちろんコルーチンとなるasync関数から使えばawaitできる点でもっと利便性の高い非同期プログラミングになりますね
>>910 非同期プログラミングは必須と主張している相手に対してスレッドの話は噛み合っていないですよ
非同期プログラミングとマルチスレッドプログラミングは別です
同期/非同期とシングルスレッド/マルチスレッドは組み合わせ4通り全てが用途ごとに使われています
>>914 そりゃ、間違ってる相手は野ざらしにしておけないからな。
放置すれば日本が衰退するから。
サーバーサイドはGo使えってのが常識になってきたっぽいぞ Rustどこで使えばいいんだよ
フットプリントが大きいと困るような低レベルなレイヤーには向いているだろうが、 ウェブアプリケーションは水平分散でなんとかなるからRailsとかも使えてたわけで
ウェブアプリじゃなくて、もっと広くサーバサイドのことを本当に言ってるなら、 主語が大きすぎてよくわからん
>>915 だからお前の頓珍漢な非同期処理を語られても困る
I/Oとプログラムが同時に動作してると言うなら単なる同期Write命令でも実際の書き込み動作はたいてい非同期
そんなこと言い出したら同期処理なんてほとんどないわな
>>921 サーバで動かすツール・コマンドのことを言ってるんじゃなかろうか
>>906 同意
ただしポーリングといっても意味合いが何種類かに分かれて
単純だがムダな状態チェックポーリングの定期もしくは常時ループもあれぱ
OSシステムコールselectなどの登録して待つタイプのポーリングもあれば
その上のレイヤで例えばRustがタスクfutureに対して状態を進めるためのポーリングなどがあり
皆の想定が異なるのかもしれない
>>910 その別スレッドを起動せずとも複数のタスクに対応できるのが非同期プログラミング
とはいえゲームのフレーム更新は常に期限が来てくれるので単純なやり方でも何とかなる
通信相手から返事が来る時間が読めないのとは違う意味で
>>915 async/awaitを含む間欠タイプを想定してコルーチンと書いてしまっていた
確かにコールバック渡し非同期関数もあるな
それなのに一つも用語の定義ができないのはなぜなんでしょう?
>>927 一言で言えば自分自身で思考する能力がないから
みな生活に余裕がないのかマウンティングしかしない もっと協力して生産的な話して
>>929 アホがえらそうにしてるのは看過できないよ。
日本が滅ぶから。
最近、プログラミングの世界で間違ってる主張が集団幻覚のように広まる
ことが多くなったから。それが、async,awaitが重要などと言う主張。
async awaitで日本が滅ぶ説は初めて聞いたな
すげーな。どうやったら滅ぶのか。 より良い代替案あれば教えてよ
>>930 「async,awaitが重要などと言う主張」をしてた人はどういう場面・状況において重要だと主張してたの?
async/awaitが重要な状況もあれば重要じゃない状況もあるだろうから文脈無しでは誰も同意しないよ
>>934 async,awaitをサポートして無い言語はダメと言ったやつが居る。
ダメな状況もあればダメじゃない状況もあるでしょ あらゆる状況でダメなものやあらゆる状況でダメじゃないものはそうないから 文脈を伴わない主張はあんまり意味がないよ
>>936 現実には、駄目な文脈はほとんど無く、皆無に近い。
ハイハイ、世の中にダメなものなんてないよねー 君以外は
>>937 >>891 あたりの発言を読む限り、「皆無に近い」の例外=「async awaitがないとダメな言語」が JS 、他の言語には async await 必要ないという主張なのかな
だとしたら async await を導入した JS 以外の言語はなぜ導入したんだろうか
特に async await を発明した C# はわざわざ新たな概念を生み出しすらしたわけだけどそのモチベーションはなんだろう
ヘルスバーグが日本を滅ぼしたかったのかな
あと JS も別に async await ではなく Promise やコールバック、ジェネレーターで同じことはできるんだけど
なぜ JS に限って async await がないとだめなんだろうか
>>940 新しい文法を追加しただけで
新たな概念は生み出してないよ
非同期プログラミングへの苦手意識は自覚してるにも関わらず 昔の知識で俺は賢いんだと虚勢を張る100点おじ 非同期プログラミングの定義すら分かっていないにも関わらず 聞き齧った知識でとにかくマウントとりたい複製おじ さて軍配はw
>>941 文法でも概念でもどっちでも良いけどわざわざ新たな機能を追加したわけでそれはどういう意図があったんだろうね
>>930 async-awaitで日本が滅ぶと主張するには根拠が足りん
async-awaitを使った場合と使わなかった場合でプログラミングにどういう問題点やデメリットが発生したのか具体的に述べよ
>>945 いや根本的に違ってくる
例えばこの数値を返してくるサイト3つからその和を求める例
let n1p = fetch(url1);
let n2p = fetch(url2);
let n3p = fetch(url3);
let sum = await n1p + await n2p + await n3p;
これをawait使わずに書くと?
>>946 スレッド起こして各スレッドの終了待ち合わせて加算するだけだろ
やってることは変わらんよ
>>948 そこは並列となるOSスレッドは使わずに
シングルOSスレッド内で非同期に並行に可能だな
>>946 そもそもそんな例は、デスクトップアプリでは有り得ない。
デスクトップアプリというのは、Word,Excel,PowerPoint,AdobePhotoshop, Illustrator,ClipStudio,各種CAD,各種3D Modeler/Renderer, 各種Simulator, PowerDirectorなどの動画編集ソフト, 音楽作成ソフトなどのことなのだから、 3箇所の別のURLからデータをfetchして足す、などというようなソフトは想定外。 ありえたとしても例外中の例外で、そんな特殊ケース、レアケースのためだけに 有用な機能を付けることは重要ではない。
>>953 C#にasync awaitを導入したのは愚かな判断だったということ?
>>945 いやそうなんだけどさ、そんな機能入れるのは愚かだと主張する人がいるので
asyncウンコード vs 80年代プログラミング
>>953 複数の非同期処理を待ち受けて結果を合成するような処理は高機能なデスクトップアプリならいくらでもやってる
Excelでも計算式はマルチスレッドでやってるしな
>>919 C/C++が使われてるケース全てだろうな
>>956 高速化のためとAPIがI/O完了の柔軟な待機に対応して無い事が有ることから
マルチスレッドでの処理は行われているが、JSのようなシングルスレッドでの
async,awaitは行われて無いし、行う価値も無い。
同期ブロッキングなプログラミングしか出来ない人はマルチスレッドに逃げるしか手がない
>>960 Win32APIの ファイルI/Oは、同期にも非同期にも対応しているが、
非同期だと柔軟性に欠けたことしか出来ず、やりたいことが出来無い事がある。
仕方が無いので、別スレッドを起動して、その中で同期的にWin32 I/Oを
使って待機状態にする。
>>959 今はOfficeをはじめとした各種デスクトップアプリで
async/awaitに相当するやり方が普通に行われてるよ
マルチスレッドだけど各スレッド内でもタスクが切り替わる形
何でかって言うとそのほうが単純なマルチスレッドモデルに比べて少ないリソースで高いパフォーマンスを出せる場合が多いから
この辺から入門してみたら?
https://docs.microsoft.com/en-us/cpp/parallel/concrt/comparing-the-concurrency-runtime-to-other-concurrency-models マルチスレッドでプログラミングできる奴が非同期プログラミングできないとか意味不明w
>>959 async/awaitは非同期プログラミングにおける便利な抽象化の一つだが
以下の2つのケースどちらの場合にも用いることができる
(1)並行(concurrent)にシングルOSスレッド内で別タスクを用いる場合
(2)並列(parallel)にマルチOSスレッドにおける別スレッドを用いる場合
どちらもawaitを用いている自分から見て非同期に別タスク/別スレッドが実行されawaitで同期的に待ち合わせとなる
各々の別タスク/別スレッドにおいて使われているのが同期I/Oか非同期I/Oかは関知外なのでどちらでもawait利用可
ただし同期I/Oを用いるとブロックされるのでシングルスレッドなら他を進められなくなりマルチスレッドなら無駄にスレッドが浪費される
>>963 実際できない人がたくさんいる
自分が賢いと思い込んでるお年寄りや
頭が固くなってるお年寄りに多い
スレッドとクリティカルセクションで考える方が
分かりやすい場合も多々あるからね
>>966 > スレッドとクリティカルセクションで考える方が
イベントとかセマフォは使わんの?
> 自分が賢いと思い込んでるお年寄りや
> 頭が固くなってるお年寄りに多い
自己紹介やね w
>>967 クリティカルセクションも知らないのか
win32脳恐るべし
>>968 > クリティカルセクションも知らないのか
どうやったらそんなアホな結論に至るの?w
レスつけるときは相手の書き込みを3回音読して読み違えてないか確認してからにしなよ
>>969 クリティカルセクションを知ってれば
「イベントとかセマフォは使わんの?」なんてアホな返しはしないから
>>970 知ってるよ
win32脳と書いてる意味を考えて
>>972 クリティカルセクションだけではどうにもならない場合もありますね
私はシグナルを併用していましたが、なにかうまくないみたいでスタベーションに悩まされたまま放置してしまいました…
>>972 > クリティカルセクションを知ってれば
> 「イベントとかセマフォは使わんの?」なんてアホな返しはしないから
どうやったらそんなアホな結論に至るの?
もしかしてイベントとかを知らんのか?w
c++ vs rust に関連する話題ほとんど出ないまま2スレ目終わりそうだけどスレ名変えた方が良いのでは?
>>975 いや、Rustには、async, await的なものがあるが、C++にはないから
C++が劣ってるなどと言う良くある間違った集団幻覚を唱える人が
後を絶たないから、C++ vs Rustの話題になってる。
>>972 クリティカルセクションが win32api に装備されている以上、クリティカルセクションを知らない者は、もはや win32 脳ですらないのでは?
てか、
>>961 は非同期I/Oの代わりに同期I/O+スレッドって言ってるんだから普通に組むならイベント通知の方が楽だと思うんだが
Rebuildの宮川さんが仕事でCとRustを使ってる模様
大雑把にI/O観点で二つに分けると 昔は同期I/Oでブロックされるからマルチスレッド 今は非同期プログラミングでスレッド数はシングルからCPUコア数が上限 RustのFutureタスク、GoのGoルーチン、JavaScriptの非同期Promiseやコールバック いずれもプロセス内スケジューラがI/O多重化(select/epoll)やタイマーなど管理して非同期プログラミングを支えている
>>980 > 今は非同期プログラミングでスレッド数はシングルからCPUコア数が上限
え?
何の言語でどのスレッド機能を使うとそんな制限にあうんだ?
ここまでディスクのコンジェスションについて言及なし
>>982 制限ではない
効率を最大限にするために敢えて用いるOSスレッド数の上限をCPUコア数までに抑えて用いるのが現在の主流
その中でタスク数を何万でも好きなだけ動かす
>>984 > 効率を最大限にするために敢えて用いるOSスレッド数の上限をCPUコア数までに抑えて用いるのが現在の主流
へー
でもさ、そのOSで動いてるプロセスは、君が作ったアプリだけじゃないんだけど
上限をCPUコア数までに押さえる理由が何かあるとすれば、他のプロセスも意識する必要あるんじゃないの?
ないの?
>>985 もちろんその通り
だから専有機なら上限で用いる
そうでないなら各configなど設定調整
>>986 > だから専有機なら上限で用いる
「現在の主流」というのは、「専有機」での話?
それとも一般的な話?
各ランタイムのデフォルトのスレッド数がどうなってるか調べれば標準的かどうか分かるんでないかね
なんかこの人、俺用語が多くて何言ってるんだかよくわかんないんだよね 「非同期 "プロセス内スケジューラ"」の検索結果 2 件 (0.30 秒) ・・・2件?
>>987 専有機とか関係なく一般的やね
例えばGoでもRustのasync_stdでもtokioでも同じ
非同期ランタイムにより使用されるスレッド数上限のデフォルト値はCPU総コア数
まともな奴いないのかよ 「"ランタイムのデフォルトのスレッド数"」で検索 "ランタイムのデフォルトのスレッド数"との一致はありません。
こいつもか 「"非同期ランタイム" "スレッド数" 上限」 約 6 件 (0.32 秒)
自分が理解できないと相手が敵かつ全て同一人物に見える病気のパターンかねw 皆普通に同じことを指している 何が理解できないのか素直に言ってごらん
-curl lud20250126144747ncaこのスレへの固定リンク: http://5chb.net/r/tech/1639539350/ ヒント: 5chスレのurlに http ://xxxx.5chb .net/xxxx のようにb を入れるだけでここでスレ保存、閲覧できます。TOPへ TOPへ
全掲示板一覧 この掲示板へ 人気スレ |
Youtube 動画
>50
>100
>200
>300
>500
>1000枚
新着画像 ↓「C vs C++ vs Rust Part.2 YouTube動画>1本 ->画像>2枚 」 を見た人も見ています:・KaZaA・Shareaza・eMule・DC++・etc 【XXXV】 ・【GTA+MC+Simcity】Voxel Turf 01 ・【PS+】PS Plus,5月のフリープレイには「STEINS;GATE 0」や「ブレイドストーム 百年戦争&ナイトメア」が登場 ・ハピネスチャージプリキュア! ++HAPPINESS CHARGE PRECURE!++ 263 ・■ ひなフェス ■ モーニング娘。'19コンサートツアー春 〜BEST WISHES!〜FINAL他 ■ dTVチャンネル(ひかりTVch+) ■ 07:30〜24:00 ■ ・那須川天心とは何だったのか?メイウェザーにフルボッコKO負け7 ・【ライフ】男35歳 “精子”の分かれ道、NHK最新不妊事情 「男性は年をとっても大丈夫という考えは誤り」 ★4 ・【コロナ】「コロナから復帰しました!ファンの皆さんきょうはよろしく!行きマウス」→ライブを中止に追い込んだ辻山孝太(30)を逮捕 ・海沿い以外の神奈川県民「町田は最高。町田駅には全てがある」←これマジ???????????? Part2 ・【パニグレ】パニシング:グレイレイヴン Part.148【Punishing Gray Raven】 ・立憲・白眞勲「もし韓国側が日本が納得する解決策を示せば関係改善に真剣に取組むか?」 ネット「朝鮮半島のスパイじゃん」「解決済み [Felis silvestris catus★] ・【パズサバ】パズル&サバイバル ゾンビの巣窟【Puzzles&Survival】 Part28 ・ウクライナ軍「ドローンで戦車を20両以上撃破」わずか1週間での目覚ましい戦果! 情報大臣も有効性をアピール [ごまカンパチ★] ・【プロ野球】 阪神タイガース、新助っ人緊急補強も メジャー35発のバルガスら有力候補 =ロサリオの不振受け ・「10万円給付のツケ」は結局、国民に…!大増税時代がやってくる★4 [みなみ★] ・[開発] VC++プログラマー涙目! DarkBASIC Pro Free ・【DMM.R18】戦国プロヴィデンス Part158©bbspink.com ©bbspink.com ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter289 ・トランプ氏、イスラエル支持を明言 TVインタビューで [首都圏の虎★] ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter287 ・【プロレス】素直な浜口京子が…グレート―O―カーンと異次元コラボ対談 プロレスラーの強さ、優しさ、皆さんに知ってもらえた! [THE FURYφ★] ・境界のRINNE 051 「ゴールドライセンス」 再放送 ◇1 ・【スターウォーズ】STAR WARS CONVERGE 01【コンバージ】 ・【SOFT】音楽聴くならSACD総合 Vol.56【HARD】 ・【PS4/PSVITA】プロ野球スピリッツ2019 Part19 ・【DQMSL】ドラゴンクエストモンスターズスーパーライト無課金スレpart3038【新生コマネチ団VSタカの団】 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter274 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter301 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter302 ・Steamプロファイルを晒すスレ Part 01 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter258 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter294 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter300 ・【悲報】コスパ良いはずの「福岡市」、家賃がグングン上昇し完全に終わる… ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter265 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter266 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter264 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter295 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter275 ・【STEINS;GATE 0】シュタインズ・ゲート ゼロ Chapter314 ・旧統一教会が5月に合同結婚式予定 宗教2世「早急に解散を」野党へ要望 [Stargazer★] ・★120124 複数 通称「K5」によるコピペ荒らし報告スレ13 ・【核問題】北朝鮮、核開発を非難した仏に猛反論 「まずは核の脅威に全くさらされていないフランスが核兵器を放棄せよ」★3 ・【日本】安倍首相「鉄道の多言語化などを一気に進めていく」 東京五輪契機に★3 ・【北海道地震】なぜ北海道全域で停電に? 専門家は「リスクへの備えが足りなかったのでは」 ★3 ・【大学受験】医学部偏差値ランキング、私大「慶應」国公立「東大」トップ [首都圏の虎★] ・【SKE48】厄介スレ146【くまっこ 前を歩く女性のパンティライン見て「誘ってるのかな?」】 ・HUGっと!プリキュア ++HUGTTO! PRECURE++ 84 ・【プレステージ】超!透け透けスケベ学園 CLASS 02 美しい裸身が透き通る、透けフェチ特濃SEX! 鈴村あいり【乱交/デカチン・巨根】 [無断転載禁止]©bbspink.com ・【現代】「性交経験ゼロ」の若者が増えている…「性の不活発化」とどう向き合うべきか [愛の戦士★] ・HUGっと!プリキュア ++HUGTTO! PRECURE++ 76 ・++クラランス Clarins++ Part11 ・switch 6000万台 vs PS5 0台 ・【朝日新聞】「保育園落ちた日本死ね」は不満を抱える市民の表現だ。国会議員の「朝日新聞死ね」は同列に出来ない ★7 ・不要なサイトをhostsファイルに加えるスレ 0.0.0.2 ・【2021年】Switch 97.54% PS4 2.35% PS5 0.09%【ソフトシェア】 ・HTS ハイテクシステム 002 ・【北海道】「旭川ってどうなってんの?」 女子高生殺人事件、内田容疑者が担当刑事と驚愕の不倫報道…「終わっている」悲憤慷慨の嵐 ★3 [樽悶★] ・【アベノミクス/奴隷特区】外国人実習生の残業代などで岐阜の繊維業者28社に法令違反 時給「400円」の業者も[01/26] ・【政治】安倍前首相は真っ青…チルドレン90人“造反”で総裁選「高市氏支持」まとまらず [首都圏の虎★] ・【DQR】ドラゴンクエストライバルズ LV1334 ・【悲報】メンタリストDaiGo、「捕まってないだけの詐欺師」という誹謗中傷を訴えて敗訴 ・【スポーツLIFE】宮澤智 専用 0605(日)【HERO'S】 ・《Royal Blues》 ◇◇◇ Schalke 04 §001 ◇◇◇ ・【ヘイトスピーチ】川崎市の審査会がツイート削除要請へ 在日コリアンの女性中傷か 不当な差別に当たると言意見一致 [ばーど★] ・【コモド】 COMODO Internet Security 01
00:47:47 up 13 days, 1:51, 1 user, load average: 7.46, 8.80, 9.46
in 2.1907098293304 sec
@0.067142963409424@0b7 on 012614