Rust part14
レス数が1000を超えています。これ以上書き込みはできません。
新スレ乙です
前スレ994流れてたので
(以下引用)
struct S;
impl Drop for S {
fn drop(&mut self) {
println!("drop");
}
}
fn main() {
S;
}
↑じゃあこれは何が所有権をもってて何がdropさせてんの?
インスタンス説のほうがまだシックリくる?
変数も所有権を持てるしスコープ終了で手放せる?
(以上引用)
この場合はmain内の
S;
のところに隠れた一時変数がいて
{ let _s = S; }
みたいに変換されると考えれば自然だと思う 前スレ>>994
匿名の一時変数(temporary)が所有者になってenclosing scopeを抜ける時にdropが呼ばれる
公式の見解とは違うけど変数じゃなくスコープが所有者になるという捉え方のほうが分かりやすければ別にそれでもいいと思う
実装的にはその方が近い >>4 >>5
それで正解。
所有権については公式がこう↓うたってんだから、値だとかインスタンスだとかいってる奴は公式に文句言えと。
4.1. What is ownership?
(ttps://doc.rust-lang.org/book/ch04-01-what-is-ownership.html)
Ownership Rules
First, let’s take a look at the ownership rules.
Keep these rules in mind as we work through the examples that illustrate them:
* Each value in Rust has a variable that’s called its owner.
* There can only be one owner at a time.
* When the owner goes out of scope, the value will be dropped. 非同期のデファクトライブラリはtokioかと思うがasync-std使ってる人おる? sqlxがasync-stdのサポート切るって聞いたけどほんと? >>5
同感
変数に入れないまま関数の戻り値となったり
その関数の戻り値が変数に入れないまま式の中で消費もしくは移動することが多い
そしてdropタイミングはスコープを抜ける時
だから変数よりもスコープが所有権を持っていると考えた方がより近いとの考えに同意する
ただし同じスコープ内で別変数へ移動させた場合もスコープ視点では移動なしとなる
それはdropに関して全く問題ないが変数間の移動を表現しきれていない
一方で属する変数もスコープも移動により次々と移り変わって行く
だから所有権と1対1でリンクしていて不変なものはインスタンスだというのも納得できるしそれ自体は正しく確定
ただし所有権と1対1でリンクしているインスタンス自体も移動していくからその移動を表現しきれていない
したがって
『所有権と1対1でリンクしているのは当然インスタンスとしつつも
そのインスタンスが代入や式や戻り値で使われるたびに変数もしくは見えない一時変数に必ず入っていると考え
さらにその変数が属するスコープの中にインスタンスが毎回イドウすると考え
他へ移動されぬまま属するスコープが消滅するとインスタンス及びその1対1となる所有権も消滅する』
というのが正確なところなのであろう
ただしそれでは学習するには長すぎるから大幅に端折って>>7の定義で良いと思う
そして学習した後で端折ってある部分が上述の長い説明だと後で理解できれば十分なのではないだろうか >>8
使っている
>>9
その議論を少し読んでみたけど
サポート続けるべきの声もある程度あるし
何らか用途ごとにもう少し抽象化したインタフェースを確立して両立利用できるようにすべき声もあるようだ
明るい未来になるとうれしい 見えない一時変数とか想像しなくても
オーナー変数がある場合は
* There can only be one owner at a time.
* When the owner goes out of scope, the value will be dropped.
で、無い場合は
* When the value ほにゃららタイミング, the value will be dropped.
と公式で書いてくれてたらスッキリなのにな >>12
一時変数は想像上の産物ではないよ
リファレンスに変数の一つとして定義されてるし
どういう時に一時変数が作られるのかも定義されてる
The Bookに詳しく書いてないだけ >>13
勉強になりました
https://doc.rust-lang.org/reference/variables.html
> A variable is a component of a stack frame, either a named function parameter,
> an anonymous temporary, or a named local variable.
https://doc.rust-lang.org/reference/expressions.html#temporaries
> When using a value expression in most place expression contexts,
> a temporary unnamed memory location is created and initialized to that value.
> The expression evaluates to that location instead, except if promoted to a static.
> The drop scope of the temporary is usually the end of the enclosing statement.
匿名一時変数は式の終わりでdropされそうやね 外部ライブラリを使わずに
コマンドライン引数の処理を昔ながらのシェルスクリプト風に処理したい場合
こんな感じでいいのでしょうか?
let mut args = std::env::args().peekable();
let cmd_name = args.next().unwrap();
let usage = || {
eprintln!("Usage: {cmd_name} [-d] [-q] [--] <target>");
std::process::exit(1);
};
let mut is_debug = false;
let mut is_quiet = false;
while let Some(b'-') = args.peek().and_then(|arg| arg.as_bytes().first()) {
let option = args.next().unwrap();
match option.as_str() {
"-d" => is_debug = true,
"-q" => is_quiet = true,
"--" => break,
_ => usage(),
}
}
if args.len() != 1 {
usage();
}
let target = args.next().unwrap();
もっと楽に記述できるよ、とか、もっと無駄を省けるよ、とか
何でもいいのでアドバイスお願いします peekableにする意味ある?
手間かかってるだけに見えるし-o output.txtみたいなオプション引数も扱えなくならない? look aheadのパターンにしたかったのかな
Peekableならnext_ifがいい感じにはまりそう
...
let mut is_debug = false;
let mut is_quiet = false;
while let Some(option) = args.next_if(|s| s.starts_with("-")) {
match option.as_str() {
"-d" => is_debug = true,
"-q" => is_quiet = true,
"--" => break,
_ => usage(),
}
}
if args.len() != 1 {
usage();
}
... >>17
そういうのは >>16にこれ追加で行けそう
"-o" => output = args.next().or_else(|| { usage(); None }), ところで
>>16の as_bytes().first() と
>>18の s.starts_with("-") はどっちが速いのかな?
今回は誤差として例えば数万行のテキストで#から始まるコメント行を除外したい場合
最善手は何? どちらも文字列の先頭数byte参照するだけだから大差ないよ
as_* じゃなくて to_* を使うとかだと差が出るかもね 短くてもいつもの汚コード氏だと分かるコードなのがすごい >>20
他にも色々方法がある
例えば落とし穴だが一番表記が短いスライス &(&s)[..1]
ただし空行をs.len()で回避した場合でも
if "#" == &(&s)[..1] { これは先頭が非ASCIIだとpanicなので注意
utf8境界を見極めて最初の1文字を取り出すには面倒で
if "#" == &(&s)[..s.char_indices().nth(1).unwrap().0] { となり本末転倒
なので最初の1文字を取り出すには普通はイテレータchars()を使って
if Some('#') == s.chars().next() { となるが
今回は正しく先頭1文字ではなく先頭1バイトを取り出せれば判断できるので
if Some(b'#') == s.bytes().next() { の方が速い
しかしイテレータを使うまでもないから
if Some(&b'#') == s.as_bytes().get(0) { と配列アクセスでも十分だろう
先頭は需要が大きいためなのか
if Some(&b'#') == s.as_bytes().first() { と専用メソッドが用意されてるようだ
ただしここでもサボって
if b'#' == s.as_bytes()[0] { とすると空行でpanicするので注意
以上ここまでは先頭取り出し系だがシンプルに
if s.starts_with("#") { が一番わかりやすい
ただしこれは実装でinline指定がないから不利で遅いかもしれない
inlineで&[u8]に読み替えるだけの as_bytes() は確実に速い
あとは get(0) と first() がどちらもinlineでコードが
前者が if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None }
後者が if let [first, ..] = self { Some(first) } else { None }
たぶん展開して最適化した最終コードは同じになるのではないか
そしてSomeやNoneは最適化で if Some(&b'#') == 部分と反応しておそらく消えると予想しているが
if let [b'#', ..] = s.as_bytes() { と最初からOption使わなければその点も確実という結論か
あとはみんなでツッコミしてくれ premature optimizationの典型例
このレベルの最適化が本当に必要ならまずは計測しろ 結論の if let [b'#', ..] = s.as_bytes() { なら可読性も落ちず意味もわかりやすいからいいんじゃね?
それを満たした上で長さが0でないことと先頭バイトの定数比較コードになると誰もが予測可能 うーんRustのデフォルトがムーブになっているのはおもしろいな
かなり思い切った設計をしている あらためてRustは凄いな
enum Optionで意味わかりやすく安全にプログラミングしつつ
生成コードからはSomeやNoneが綺麗に跡形もなく消え去ってC言語で書いたときと同じになるんだな ML系言語の概念とC的な低レイヤの概念を融合した上で
オブジェクトの依存性の概念も付け加えるというのは実に素晴らしい考えだと私も思う。
個人的には Haskell が好きなんだけどランタイムサポートが重すぎると思ってたので Rust は大歓迎だ。 ヒープを使うか使わないかと
dynを使うか使わないかの2点だけは
コンパイラも最適化できないのでそれだけ気をつけていれば大丈夫 >>32
boxを使わない時は常にスタックじゃないの? >>33
BoxだけでなくVecやStringなどもヒープを使う
配列[T;N]や配列を使ったArrayVecやArrayStringなどはスタック上のみ使う
dynはBox<dyn ...>の形ならヒープ上だけど&dynの形ならスタック上のみで使うことができる >&dynの形ならスタック上のみで使うことができる
ん? >>35
例えば標準入力stdin()とファイルFile::open()は型がStdinとFileで異なるが
どちらもtrait Readを実装しているから&mut dyn Readに入れることで同じコードでreadできるようになる
このdyn Traitをtrait objectと言って動的ディスパッチとなるが生成コードは一つになる
ちなみにimpl Traitだとコンパイル時に静的に解決されて生成コードは型毎に多数のコードが生成される
trait objectは?Sizedだから直接は扱わずに&dynの形かBox<dyn>の形で使うことになる
&dynの形ならスタック上のみで使うことができるが元の型よりは長く生きられない制限がある
そこで例えば関数の返り値にしたい時などはヒープを使ってBox<dyn>の形にして返す Box<T>の形ならヒープ上だけど
&Tの形ならスタック上のみで使うことができる
と言われたら、ん?ってならない? ヒープ使わないんだったら、そりゃスタックになるが、
そもそもなにか勘違いしてない? &dyn の形ならスタックで "も" 使うことができる
ってこと? dynはヒープを使わない
しかしサイズが不定
つまりdyn型の変数はない
スタック上で使う時は&dyn型の変数に入れて用いる
戻り値にしたいならBox<dyn Trait>
これはヒープ使うことになる (stable rustでは) dyn 型の変数はない
が正しい >>40
strはヒープを使わない
しかしサイズが不定
つまりstr型の変数はない
スタック上で使う時は&str型の変数に入れて用いる
戻り値にしたいならBox<str>
これはヒープ使うことになる
これでも
んー・・・ってならないならもういいや その置き換えは無理があるんじゃないか
&strは単なる参照で&strの一部でもStringの一部でも代入できる
&dyn Traitはそれを実装する具体型を代入することで生成される &dynの参照先はヒープ(例えばBoxの中身)の可能性もあるからヒープを使わないって表現は誤解を招きそう >>41
stable前提話でごめん
unsized localがstableとなるには
一旦可変長配列を切り離さないと厳しい?
>>44
そんなことを書いてる人はいない
俺が書いた分も、dyn自体は(arrayなどと同様に)ヒープを使わない、だけだぞ
しかもその後にBoxでヒープを使う話もしている >>43
&strがstrへの参照であるように
&dyn Traitもdyn Traitへ単なる参照
&strにStringを代入すればDerefがstrを生成してるように
&dyn ReadにFileを代入すればコンパイラがdyn Readを生成してる
BoxだけでなくRc<dyn Trait>とかも使えるからね >>46
自己矛盾を起こしているぞ2点も
まず1点目
前者はターゲットstrでimpl Deref for String実装というコードが実際にありその枠組みに従った規定通りの操作
後者はそのような枠組みも実装コードも公開されていない操作
次に2点目
前者はStringの一部を指しているだけであり何か新たな実体を生成してそこを指しているわけではない
後者はFileとは別にvtableなどの実体を生成している
このように明白に異なる >>47
strとtrait objectという別のものなんだから違いがあるのは当たり前
>>40と>>42の対比が成立しないと言えるような違いを指摘しないと意味ないよ >>47
>前者はStringの一部を指しているだけであり何か新たな実体を生成してそこを指しているわけではない
>後者はFileとは別にvtableなどの実体を生成している
ああ、なるほど
trait objectが生成されるときにvtableも生成されると思ってるのか dynにキャストするときにコンパイラがfat pointerから参照させる用のvtableを生成することを指しているのでは? >>48
そのように大きく違いのある全く別のものを対比させるのは無意味なので、置き換えは無理があるんじゃないか、と書いた
>>49
そこは実行時にvtableを生成とも誤解しかねない書き方をしてすまん
vtable自体は型とtraitのペアで静的に確定するものでありコンパイル時に生成している >>50,51
vtableはtrait objectの有無に限らずtrait実装につき1つコンパイル時に作成されそれが共有して使われる
vtableを指すtrait objectも実行時じゃなくコンパイル時に作成される
実行時にはvtable経由のダイナミックディスパッチが発生するだけ >>52
そうか、crate内で静的ディスパッチしかしてなくても他crateからtrait objectとして使われる場合もあるから常にvtableは生成されるのね
ちなみに、object safeでないtraitについては生成されない (できない) よね? >>53
trait objectとして使われなくても常にvtableが作成されるかどうかはコンパイラの最適化の話だからここでは関係ないよね
実際のところはdylibじゃなければコンパイル時に使われないことがはっきりしてるはずだから作られないと思うけど >>55
コンパイル時じゃなくてリンク時の最適化の話じゃないの
オブジェクトファイルには常にvtable埋め込まれてるのかと
それとも dyn Trait を使った側のcrateのオブジェクトファイルにvtableは埋め込まれる? >>51
>> vtable自体は型とtraitのペアで静的に確定するものでありコンパイル時に生成
>>52
>> vtableはtrait objectの有無に限らずtrait実装につき1つコンパイル時に作成
この件だがコンパイラのソースを見ると
必要となる型の分だけコンパイル時にvtableを作成してるよな
https://github.com/rust-lang/rust/blob/stable/compiler/rustc_codegen_ssa/src/meth.rs#L53 crateあたり同一traitのvtableは最大一つ生成されるということかな 同一traitが複数の型で実装されてたらその型ごとに作られるはず 各型毎にtrait objectやvtableはこういう構造になっている
let mut stdin: std::io::Stdin = std::io::stdin();
let addr_stdin = addr!(stdin); // &mut借用する前にアドレスを得ておく
let dyn_stdin: &mut dyn std::io::Read = &mut stdin; // ここで dyn Readのtrait object作成
assert_eq!(val!(addr!(dyn_stdin), 0), addr_stdin); // 前半は元のstdinを指している
// assert_eq!(val!(addr!(dyn_stdin), 1), 【Stdin用のvtable】); // 後半はStdin用vtableをを指している
assert_eq!(val!(val!(addr!(dyn_stdin), 1), 3), <std::io::Stdin as std::io::Read>::read as usize);
assert_eq!(val!(val!(addr!(dyn_stdin), 1), 4), <std::io::Stdin as std::io::Read>::read_vectored as usize);
別の型でも同じようにdyn Read作成
let mut file: std::fs::File = std::fs::File::open("/dev/null").unwrap();
let addr_file = addr!(file);
let dyn_file: &mut dyn std::io::Read = &mut file; // trait object作成
assert_eq!(val!(addr!(dyn_file), 0), addr_file); // 前半は元のfileを指している
// assert_eq!(val!(addr!(dyn_stdin), 1), 【File用のvtable】); // 後半はFile用vtableをを指している
assert_eq!(val!(val!(addr!(dyn_file), 1), 3), <std::fs::File as std::io::Read>::read as usize);
assert_eq!(val!(val!(addr!(dyn_file), 1), 4), <std::fs::File as std::io::Read>::read_vectored as usize);
上述Stdinの時と同じ位置にFile用のread()やread_vectored()がvtableに入っていることがわかる
したがって>>59や>>51が正しいと思う
各trait毎にvtableのメソッドの位置が決まり
そのtraitを実装する各型毎にvtableが作成される traitをimplした型が違ったら対応するfnの中身も違うので
同じtraitでも実装された型ごとに違うvtable作らなきゃいけないのは確かに当然か
>>60
異なるcrateからtrait object生成した場合にvtableは同じアドレスのものになるの?
それとも、異なるものになるの? >>57
「trait objectを使うようなコードが一切存在しなくても」vtableが作られると言いたかったわけではないんだが書き方が悪かったね vtable自体はデバッグビルドのasmやllvm-irで確認できるよ
例えばxという名前のメソッド1つだけ持つFooトレイトのi32実装ならこんな形でvtableが出力される
.quad core::ptr::drop_in_place<i32>
.asciz "¥004¥000¥000¥000¥000¥000¥000¥000¥004¥000¥000¥000¥000¥000¥000"
.quad <i32 as playground::Foo>::x >>61
crateごとじゃなくcodegen unitごとにvtableが作成される可能性が一応ある
crateが違っても必ずしも複数のvtableができるわけではない >>64
前者は分かるんだけど後者はどういう時にそうなるの?
依存crateにvtableが含まれてる場合? >>60
もう少しvtableの情報を詳細にした
let mut file: std::fs::File = std::fs::File::open("/dev/null").unwrap();
let addr_file = addr!(file);
let dyn_file: &mut dyn std::io::Read = &mut file;
という状況で以下が成立
assert_eq!(val!(addr!(dyn_file), 0), addr_file);
let vtable_file = val!(addr!(dyn_file), 1);
assert_eq!(val!(vtable_file, 0), std::ptr::drop_in_place::<std::fs::File> as usize);
assert_eq!(val!(vtable_file, 1), std::mem::size_of::<std::fs::File>());
assert_eq!(val!(vtable_file, 2), std::mem::align_of::<std::fs::File>());
assert_eq!(val!(vtable_file, 3), <std::fs::File as std::io::Read>::read as usize);
assert_eq!(val!(vtable_file, 4), <std::fs::File as std::io::Read>::read_vectored as usize);
つまり型情報が消失したdynにおいてもこのvtableさえ保持していれば正しくトレイトメソッドやデストラクタを呼び出せる
>>65
そのコードだと比較しようとしているのはvtableやそのアドレスではなく
上述コードでのdyn_fileのアドレスを比較しているだけなのでそもそも前提が謎だな
さらにvtableの内容は各型に完全に依存しているからmergeの意味もよくわからない 空traitなんかは異なる型同士でvtable使い回しできるのでは
あとは全associated fnにデフォルト実装が与えられていて中身が全く同じものとか
いずれにせよLLVMがよしなに最適化してくれるとかなのでは? vtableにはデストラクタも乗ってるようだけどそれも必要ない場合あるもんな
>>67の状況も今後実装が変わったり最適化で消えたり色々ありうるわけだ
いずれにせよ我々は興味本位で語り合ってるだけであり
このあたりの非公開の仕様に依存したコードを書いてはいけないしな >>67
>上述コードでのdyn_fileのアドレスを比較しているだけなのでそもそも前提が謎だな
Rc::ptr_eqで単純に比較するとfat pointer内のdataへのpointerとvtableへのpointerの両方が一致してるかのテストになる
>さらにvtableの内容は各型に完全に依存しているからmergeの意味もよくわからない
わかりやすいのは&Tと&mut Tのように可視性のみ違う場合 >>70
dataへのpointerの一致を見てるなら
型を含めた一致が保証される? >>66
>依存crateにvtableが含まれてる場合?
そうだね
依存crateに含まれてても同じ内容のvtableができる場合もあるみたいだからいくつか条件があるみたいだけど >>71
std::ptr::eqでdataへのpointerを比較すれば保証されると思うよ プロジェクトのディレクトリの外から
$ cargo run
するときってどうやってプロジェクト (ディレクトリ) を指定するの? >>74
用途が違うかもしれんがworkspace配下からなら-p <package-name>で指定できる >>70
vtableがmergeされるのかどうか
trait定義methodの定数返しと最適化されやすいようにして
さらに &T と &mut T でやってみたがtableは別々になった
まず最初の原因はvtable最初の要素である以下が成立していないためとわかった
assert_eq!(std::ptr::drop_in_place::<&i32> as usize, std::ptr::drop_in_place::<&mut i32> as usize);
ところが--releaseにすると上記は成立するようになった
同様にtrait定義methodも--releaseにすると同じアドレスとなった
つまりこういう実験において--releaseオプションは必須
そしてvtableの内容は全て完全に一致
しかしvtableのアドレス(格納場所)は異なり別々のvtableのままであった LLVMの最適化で何が行われるかrust側では保証できないから >>65 みたいに同一性について保証しないって仕様になっているんだろうね そういえばRustってC++とかFortranみたいに最適化で結果変わる可能性ってあるの? >>77 がその結果の変わる一例では、ってことではない? >>77は内部構造が変わるという話で出力が変わるという話ではないと思っていた >>79
Rustは他の言語と違い、UB (undefined behavior)すなわち未定義動作を基本的に起こさないように安全に設計されている
最適化オプションの有無でもその点は大丈夫
もちろん念のためだが、入力が異なれば結果は変わるし、非同期の実行タイミングは当然保証されないから実行順序に依存するコードは結果が変わり得る
そういうことでないならば結果は同じになる
ちなみにvtableの件は仕様が公開すらされていない内部情報の話
しかもそこに収容される関数のアドレスの値やvtableのアドレスの値というプログラマーが全く気にする必要ない話
だからこれらは変化してももちろん良くてそれを承知の上で盛り上がってるだけ vtableの話は元々のスタックやヒープの話と関係あったの? asm!とdestructuring assignmentかな inline asm安定化は嬉しい、stableでベアメタルやりやすくなるかも 同じやつかもしれんが、スレ違いの指摘を聞かない馬鹿3名引き取ってくれ
ID:u7rOKKj6
ID:iu2arc+w
ID:aDhOSI3t rustのバージョンごとのリリース予定機能ってどこかにまとまってるの?
betaに入ったものはだいたいそのままstableになるから事前にどの機能が来るのか分かると思うんだが
いつもstableリリースのブログ投稿で知るので、もっと早めに知れると嬉しい Rust コンパイラのリリースサイクルは六週間という時間で区切ってるから
その時点で確定してるものが入るって感じじゃないの。
次のリリースまでにこれとこれを……というようなマイルストーン方式ではない。 最近12週間でnightly(master)でstabilizeされた機能一覧とか
最近6週間でbetaに入った機能一覧を知る方法ない?って意図だった Electronの代替を目指す軽量なRust製フレームワーク「Tauri」、リリース候補版に到達
https://www.publickey1.jp/blog/22/electronrusttauri.html
Electronの優れた特徴を備えつつ、よりメモリ消費量が小さくファイルサイズもコンパクトで、高いセキュリティを備え、柔軟なライセンスを実現しようと開発されたのが「Tauri」です。
GitHubにはElectronとの比較表が示されています。それによるとLinux版のインストールサイズがElectronで52.1MBのところ、Tauriは10分の1以下のわずか3.1MB。同じくLinux版でのメモリ消費量はElectronが462MBのところ、Tauriは半分以下の180MBとなっています。
起動時間もElectronの0.80秒に対してTauriは0.39秒です。 モバイル版も予定されてるとなるとFlutterにも似てるかな
あっちはモバイルベースのフレームワークだけど rustで複数のプロセスで「共有メモリ」したい場合ってどうすればいいの? プロセス間だとCと大して変わらないと思う
libcのmmapとかでアドレスに共有ファイルを割り当ててそのポインタをBoxもどきで包む
Drop時にfreeじゃなくmunmapするBoxっぽい別の型が必要でプロセス間のロックとか考えるともっと面倒くさい
mmapでcrate検索すれば使えるのがあるかもしれない 基本的には >>103 の言うとおり C と変わらないと思う
shared_memoryというLinuxとWindowsで使えるクロスプラットフォームなcrateもあるみたいだね
ただプロセス間でメモリを共有する場合に複数プロセスから同一領域に対して &mut 参照を作っちゃうと UB にならないかは気になる >>100
WebViewなら大して変わらんじゃないか
がっかり むしろ、rustでプロセス間通信をする場合に相性が良いのは何か、というのが本質では無いだろうか?
プロセス間共有メモリをrust的に安全になるように包むことは可能なのか?
パイプやソケットの再実装にならないか? 本当に共有メモリが必要なのか?って所だよな
ベアメタル開発時のハードウェアみたいに必須のケースもあるけど メッセージキューのほうが安全かね。
速度と手間は犠牲になりそうだけど。 どういう問題を解決したいかという文脈抜きに
どういう手段がいいかを論じても意味ないよ
いわゆるXY problem >>107
共有メモリをミューテクスで排他制御するならロックの取得/解放をメモリの取得/解放と同等に扱えるような気はするが volatileアクセスするのが自然なんじゃねーの。 >>112
volataileはプロセス間のリソース共有とは概念的には別の話。 少なくともCでは
CON02-C. volatile を同期用プリミティブとして使用しない
ttps://www.jpcert.or.jp/sc-rules/c-con02-c.html
だけど、Rustは同期が保証されるんだっけ? 全ての共有メモリのページアクセスに対して割込みをかけてるならそういう実装も可能だろうけど、現実的には考えにくいだろうw
アホなこと考える前に自分でコード読めよw >>100
そのTauriに興味を持ったのですが
それはJSの使用を限りなく小さくできますか? Rustみたいな標準ライブラリが未熟で安全性のかけらもなく、野良のゴミコードばかりの言語ありがたがって使うアホいないよなw >>121
Javaもそう言われてたけどなw20年くらい前 20年くらい前のJavaはSunの強力な後押しでつよつよだったからなw
ソフト資産も順当に増えたw 安全性はRustの比じゃないし、らいとわんすらんえびうぇあと嘯いてたw >>123
たしかにヌルポなどJavaの安全性は低いけど
RustはJavaとは異なりその点も安全性が保証される言語だから
実際にJavaからRustへの移行も進んでいる ぬるぽなどの安全性!?ぬるぽなんて安全そのもので代名詞みたいなもんだろうw >>124
それ以外にもJavaは実行時エラー(例外)が多すぎですね
Rustはコンパイル時にエラー検出してくれるものが多いだけでなく
実行時エラーとなるものでもResultやOptionで返すからエラー処理忘れが起きないけど
Javaは忘れていても通ってしまい実行時にレア発生するものだと本運用で例外発生で落ちたり Rustでも雑にunwrap使ったらpanicで死ぬ可能性あるよね そんなこと起きないし
Rustみたいに
誰もコーディングできません
聞ける人いません
ライブラリありません
エラーわかりません
とか言われないw リリース前にunwrap全部消しとかないと叩かれるの? どんな言語でもロジックミスでプログラムが終了することはいくらでもあるw
安全というのはそういう事態が起きてもプログラムがsegmentation faultなどで落ちないことw
よりよい実装方法はあるけど、それはそれw
まあリリース後にpanicで終了するのは製品ならやばいw >>132
可能な限りunwrap()は避けたほうがよいでしょう
もちろん続行不可能なために意図的にpanic終了させたい場合は別です
ロジック的にここでは絶対にNoneやErrが来ないはず!(と思い込んでいる)ケースもありますが
それならばせめてその理由を記述したexpect()を呼ぶように変えることで
発生時対処やコードをレビューする人にも役立つと思います unwrapなんていくらでもそこら中で使ってるだろw
流石Rust wwww もちろん誰が見ても起きないとわかる自明な場合はunwrap()でいいと思いますよ
自明でない場合はせめてコメントに理由を残すとよいでしょう
自分で書いたコードでも1年後に「ここでunwrap()大丈夫だっけ?」と忘れてることもありうるためw そんなのは誰がどんな理由でどう書いたってその人の自由w
他の人がどう思うかを気にするなら、べき論くらいは知っててもいい程度の話w unwrapはunwrapで死ぬけどヌルポはしばらく動いてから死ぬという地味な怖さがある RustがJavaやC#より安全なわけないだろw 頭悪すぎw >>139
Rustの方が安全
Rustはデータ競合安全性もコンパイラが保証 unsafeこんもりのRustが安全なわけないだろw もしかして手元のCコードをRustにベタ移植してる?
コンパイル通すためにunsafeこんもりなら納得できるが まあいうほど安全だったらもっと早く全てrustに置き換わってるわな。 何ヶ月か前にもいたな。Rustのいう安全とは何かを知る気が一切無いまま、安全じゃないって煽ってたやつが Rustはunsafeを隠蔽し、しかも内包する動機を安全の核とする部分に持つ劇的矛盾言語w
それを安全安全高速と謳って騙ってベアメタル領域に行ってみたり、他スレまでしゃしゃり出るうざさw
マジで迷惑w
firefoxだけで使って大人しくしとけw ネガキャンしようが
ttps://foundation.rust-lang.org/members/
これが現実w 俺が出したやつじゃんw
あのときも言ったけど、その辺の巨人は必要のあるニッチな領域を持ってるからバックにいるだけw
あのときからマジでRust推しがウザすぎてRust推すのやめたんだよなw >>126
Rustは何でもは知りません
知ってることだけ知ってます tauri触ってみたけどRust⇔JSの値のやりとりはJSON限定なのかな
Responseのbodyにバイナリデータ入れて返す方法を探してるけど
iframe内で送受信するオプションがあるからできないかもしれない 154だけどBuilderのregister_uri_scheme_protocolでいけそう
WebViewのIPCをちょっと勘違いしてた 全く使ってないけど結局js使うんならややこしくなるだけだろw
electronでwasm使ってウンウン唸ってる層にしか刺さらないように見えるのに宣伝うるさすぎw
しかもRust推しの数字操作は常にえげつないw
実効果と桁が違う宣伝効果をタイトルに持ってきちゃうw 詐欺かよw js周りで言えばdenoとか最近どうなん?
わざわざ作り直した挙げ句、「全然速くなってませんでした!!!!少し設定とか出来るから許して…てへw」では困るだろw
いろいろ足りない処理もあるし、ベンチ向けに偏りすぎてると思うけど、後発ならjust-jsとか特定用途で高速化・コンパクト化できている
この差は何なんだろう? denoってセキュリティ周りをどうにかするのがモチベーションで高速であることは謳ってないのでは >>157
内部処理もUI周りも全部同じ言語で書いた方が楽って層には敬遠されそうだけど
内部処理はRust、UI周りはHTML+JSの方が書きやすいって層には需要があると思う
electronはよく知らないけどWebViewはバイナリにブラウザ埋め込む感じだから
ブラウザ内でバイナリ実行するwasmとはあまり関係ないかも >>159
作者のモチベーションがどうというより、ユーザー視点だとわざわざ書き直したにしてはパッとしないってこと
しかも書きっぷりまで変わるんではちょっとね
V8の上側にRust入ってるのになぁ〜w
>>160
> 内部処理はRust、UI周りはHTML+JSの方が書きやすいって層
wasm使う層だよねw
> electronはよく知らないけどWebViewはバイナリにブラウザ埋め込む感じだから
> ブラウザ内でバイナリ実行するwasmとはあまり関係ないかも
埋め込むというかバイナリをくっつけるだけでしょw
包含関係が逆なだけで酷似してるし、問題も似たような問題ばかりw
wasmならwebでそのまま動くが、tauriだとplatform限定されてnativeな分Rust側の速度が速いってだけw Rustでそんな便利な状況になっているのか
tauriというのをちょっと試してみるかな tauri自体うんぬんじゃなくて、electronクラスのメジャーミドルにまでRustでの書き換えが浸透してきてるってこと
すなわちRustがシステムプログラミングのデファクトスタンダードになったってことを表すエビデンスが1つ増えた 逆だよw
electronはそもそもjsでアプリを書こうというものであって、ごく一部のクソメジャーアプリを除けばjsの範疇を出ないし、クソメジャーアプリはもうそれ自体がプラットフォームと化してるからカウントできないw
C#で書けば楽に何でも書けるのになんでわざわざHTML+JS+Rustを不自由なフレームまで使って書きたがるのか・・・ユーザーは不便、開発者も面倒とメリットなんて全くないのにw
結局ただの自己満足なんだよね Macは知らんが、Linuxのどこにそんな事実があるの? ID:oRBcPyqIはあちこちのスレで
的外れなRust叩きをやってるけど
なんなんやろ 誰も言及してないC#とか唐突に言い出すあたりでお里が知れる あちこちのスレで長期間スレ違い指摘を無視して嘘八百並べるRust推しがいたからでは?w >>167
やっかみだろ
書けない人には絶対書けない言語だしな
C/C++もそうだがJSちょっとかじった程度のスクリプトキディが書ける言語ではないと言う認識を持ってほしいね RustのスレでRustの話して文句言われる筋合いはないw その辺の言語は普通にかけるけどなw
Rustが安全とか嘯くアホよりはマシだと思うぞw Rust書けるようになるためにはまずGC言語への依存を捨てろ
自力でメモリ管理できる能力が絶対に必要
スタック、ヒープ、Dropトレイト、所有権、借用ルール、(可変参照と不変参照)、Box、arena、Rc、Cell、RefCell
この辺り曖昧さなく完全に理解してないと書けない言語なの
無能にはかけない言語 GC書いたことあるけどw
Rustなんて誰も書ける必要のない言語なだけw Rustは悲惨な言語だよ
JS書いてブイブイ言わせてるようなやつが全く赤子みたいになるんだからw 別にC#もJavaも・・・ってか大抵のメジャー言語は書けるけどw >>173
追加
Derefトレイト、Copyトレイト、Cloneトレイト
こいつらは必ずしも必要ではないがメモリの使い方の訓練にはなるので触っておくべき
逆にこれらを理解できればRustは書ける
C#おじさんガンガレ アホだなw 俺はRustを書けないなどと一言も言ってないw
そしてC#おじさんとか意味不明な名前を付けられてる人でもないw 誰も書けるようになる必要のない言語なのは間違いないw
理由は>>177のリンクのとおりw >>185
お前に効いてるだけだろ
>>186
Rust以外の言語なら何でも Rustもコンプレックスの対象になるんか…
ただのプログラム言語なのに >>188
最近はもうご無沙汰してるけどemacs使ってたよ
>>189
コンプレックスではなく、広めるメリットのないゴ○言語だよねって言ってる >>190
EmacsLispとCommonLispじゃ全然違うぞ TauriをJavaScriptを一切書かずRustだけで使うのに挑戦し始めました
とりあえず公式に従いcargo利用パターンでやってみる
$ cargo install tauri-cli --locked --version ^1.0.0-rc
これで bin/cargo-tauri がインストールされて cargo tauri XXX が使えるようになった
$ cargo tauri init
これで src-tauri というディレクトリができて tauri.conf.json に指定すればよいのか
どうやらwasmを入れてやればTauri利用でもブラウザ利用でもRustコードだけで済むっぽい
$ rustup target add wasm32-unknown-unknown
$ cargo install trunk
$ cargo install wasm-bindgen-cli
これで bin/trunk などRustでのWASM使用環境が入ったようだ
次にフロントエンド用のディレクトリを作る
$ cargo new --bin frontend
$ cd frontend
ここで index.html を以下のdata-trunkを含む行でcssなど指定して適当に作成
<link data-trunk rel="css" href="/public/main.css"/>
$ trunk build
$ trunk serve
これでサーバーが起動された
まずはブラウザから http://localhost:8080/ により無コードwasm環境動作確認OK
これでようやくTauriに戻って先ほどの tauri.conf.json に今の分を記述
"devPath": "http://localhost:8080",
"beforeDevCommand": "cd frontend && trunk serve",
"beforeBuildCommand": "cd frontend && trunk build",
$ cargo tauri dev
これで無事にTauriのウインドウがついに出てきた!ので無事に初期環境が成功
さてここからRustコードはどのフレームワークで書くのがおすすめ? >>191
どれもLispでそんな違いがあるとは思ってなかったし、そんな思い入れねーよ
>>192
wasm入れてpure rustは面白い試み
terminal作ってくれ >>193
どれもLispでそんな違いがあるとは思ってなかったし、
なんだ素人だったwwwww
馬脚を表したなwww この人ぼくはプログラミングにはくわしいんだと
わめくほどボロが色々出て面白いな >>192の続き
とりあえずRust製フロントエンドフレームワークYewを使用
先程のfrontendディレクトリで
[dependencies]
yew = "0.19.3"
を Cargo.toml に追加して src/main.rs に以下のハローワールド記述
use yew::prelude::*;
fn main() {
yew::start_app::<App>();
}
#[function_component(App)]
pub fn app() -> Html {
html! {
<div>
<h2 class={"heading"}>{"ハローワールド!"}</h2>
</div>
}
}
そしてTauri側で再び
$ cargo tauri dev
無事にTauriでハローワールド!が出ました
同様にブラウザから http://localhost:8080/ でも同内容が表示された
つまりRustコードを書くだけで『デスクトップアプリ』と『ウェブアプリ』が同時に出来上がる?
もうじきTauriがモバイル対応するそうなので『モバイルアプリ』にもなるということ? Yewはマジでelmっぽくて嫌いじゃないが、htmlの部分が一切補完効かないの結構キツい >>199
もちろんTauriと関係なくTauriを使わずとも
YewやWozなどのRustによるfrontend frameworkを使って
RustだけでPWAを作ってWebブラウザ上で動かすことが出来る
Tauriはそれに加えてデスクトップで動かすことが出来る
つまりWebによる制限を超えた動作も可能でデスクトップアプリとなる Elmっぽいのが好きならElmで書けよ
変数がmutableなRustにはTEAは向いてないだろ >>202
今どきHTMLを手で書く人はいないので問題ない
あくまでも雛形となる最小限のみを書く >>204
Elmって状態が深くなってきたら更新するのしんどくね?
正直mutableな方が楽だと思ってるわ
>>205
うーん >>194
別に大差ないと思うけどな
>>196
そのときの都合
>>197
Lispがゴミというのならそうだと思ってたけど
そうでないLispがあるなら、どれで理由は何なの?
>>198
中を見れない普通のwebフロントを書きたいか、凝ってて動作がもっさりしないように作りたいのならいいのかもしれんが、それだけのために言語的制約がきつく、誰もメンテできなくなるRustをわざわざ使う理由はないな
しかもそれをデスクトップアプリでとなるとさらに微妙
結論だけいうと、そういうのを喜ぶ人向けという非常に狭い用途 >>207
Allegro CL。このくらいは知ってるよね? >>198
一言で言うともっとデスクトップアプリっぽいのを作ってほしかった
ただのweb画面ならReact Nativeでもcordovaでも使った方がメンテ出来ていいかもしれない
webはう〜んかもだけどFlutterでもいいし、Rust+Qtとかでもいい
>>208
そんなマニアックなの誰も知らねーよ。理由は何なの? >>207
ウェブのフロントエンドかデスクトップアプリの用途でrustを使うのは微妙って言ってたのかな? >>212
伝わらないなら受け取ったとおりのことを言ってくれればいいよ
せっかくRustだけで書ける環境を思いついたのに、ローカルで結局Webフロントメインのコードになっちゃったから残念な気持ちになっただけ
せっかくRustだけなのにフロント側でPWAとかもうアホの極みだろ? openglベースのeguiの方がまだマシ
https://github.com/emilk/egui
ただlinux(ubuntu20.04)だとexampleすら動かない
$ cargo run --release
Finished release [optimized] target(s) in 0.09s
Running `target/release/eframe_template`
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
eframe_template: ../../src/xcb_io.c:260: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
中止 (コアダンプ)
$
まあ安全なRustだからしょうがないよね
wasmにしたら動いたけど、いろいろインストールして回る割にwasm-optがなくて躓いた(パス通してないので) エコシステムが不足しすぎて不安定すぎなのに詐欺っぽい宣伝ばかり先行してて、まともな人ほど寄り付きにくい状況になってるのが問題 >>209
Rust frontend frameworkは10種類以上あるから好みのものを選べばよい
もちろん仮想DOMを使うReact的なものから対照的なSvelte的なものまで色々ある
>>213
むしろPWA含めたWebアプリ全般でCSRだけでなくSSR/SSGが重要との認識が一般的になった今だからこそRust利用が重要視されている
当然isomorphicにrenderingするわけだから従来はReact/Next.js Vue/Nuxt.jsといったようにサーバー側でもJavaScriptを使わざるを得えず遅くて重いことが課題となっている
そのため両サイドでRustによるframeworkを採用することで従来の課題を解決するのが最新動向 >>218
まるで10種もあるのはメリットのように書いてるけど、デファクトがなくて労力分散されてる上にユーザーも10種吟味しないといけないのは普通にデメリットだからな >>218
tauriに対する話なんでクライアント側
最終的なレンダリングをHTMLにしたいからって何が嬉しくてローカルでWebのPWA持ってくんの?
ウィジェット遠すぎてネイティブRustにする意味がないだろ
SSR/SSGのロジックをRustで書きたい話とか関係ないし、大層な結果も出ていない
Rustフロント周りのフレームで使えるモジュールはいくつか出てきているという程度で、高い品質のものが向き不向きや好みに応じて選べるような印象とはほど遠いが、いずれにせよ今回の話とは無関係 やっぱりワッチョイ導入して一週間NGできるようにすべきだったんだよ >>213
お主フロントエンドフレームワークスレでRustを叩き棒にして荒らしてたヤベー奴じゃな?
書き込み内容やクセといい、書き込み時間といい。 >>222
ヤベー奴はお前
俺はそんなスレ見たことすらない じゃぁ別人だったとしてC#erはヤベー奴が多いんだなぁ。覚えとこ >>224
今どきC#なんて大抵の奴が使えると思うが…
今Rustを「推して」いるやつは頭がヤバイ奴ばかりなんだな >>219
JavaScriptのフレームワークは何十種類も無数にあり長い歴史の中では最近と言ってよいほど後発のフレームワークが勝ち残っているのは事実だが
そのように自由な競争があるからこそ良いものがどんどん出てくる
Rustの各分野のライブラリも同様であり利用者による健全な民主主義が機能している良きRustの方針
>>220
Tauriの話は一切していない
PWAやWebアプリと明記しているようにWebブラウザにおけるフレームワークのRustの話
CSRとSSRおよびSSGにおいて同じロジックでDOMやHTMLへレンダリングするのは事実
そしてそのコードをサーバーサイドとフロントエンドで共有しないとコード開発効率がよくないのも事実
そのため現状ではそのコードのプログラミング言語がJavaScriptとなっているがサーバーサイドで重く遅い
そこで多くの開発者たちがRustを採用したフレームワークを開発することでその解決を計っている
ブラウザ側ではWASMとなるがGCランタイムのある言語は不利なためRustが選ばれ使われている 健全な民主主義じゃなくて野生のまま鼻息荒い馬鹿が闊歩してグチャグチャにするだけのRust界
tauriの話しかしてないところにレスで「Tauriの話は一切していない」とかアホすぎる
Rustが件の調査で1番だったのはGCランタイムとか関係なく、安全で速いと嘯かれた人が騙されて使用してるだけ
実際には苦労して書いても速くなく、unsafeを使って初めて速くなるか、回りくどい方法を使わないと普通に書くより遅くなる
wasm自体の実体は多分ゲームが一番多いと思うので、実際はC#が強いと思う >>229
> 実際には苦労して書いても速くなく、unsafeを使って初めて速くなるか、回りくどい方法を使わないと普通に書くより遅くなる
普通に書いたら遅くなったコード例ください >>228
自由なライブラリが無数にある状況を良しとするとならcommon lispも良しとしてそう Common Lispと同じで一部のマニアが熱狂したままで一般に浸透せずそのまま死ぬ未来が見える >>229
君が文脈を読めない人だから君だけが誤解している
例えば分かりやすく「PWA」という単語でこのスレを検索すると皆はTauriとは別の話をしていることがすぐ分かる
もちろんPWAの意味するところもWebブラウザ上での動作でありTauriの話とは別の話であると皆は分かっているためである
もう一つ君はRustにおけるunsafeの意味と位置づけを理解していないようだからそのような意味不明な発言となっているのだろう
>>233
ほとんどのメジャーなプログラミング言語では多数のフレームワークが競い合って良いものが残った
そうでない言語があるなら教えて欲しい
よほど特殊な例外だとわかるだろう >>237
良い物以外が死ぬくらい強いのがあればいいんだよ。生き残ってきた言語はそうだった。だけど今のrustはそうはなってないのがいかん
状況はcommon lispに近い >>238
強いもの1つだけが残る死の世界を望む人はいないしそんな現実もない
例えばJavaScriptのフレームワークの最新シェアを見ても1位は31%しかなく2位が12%で3位が11%とこの3つでようやく過半数
それぞれ特徴の異なるフレームワークが多数共存していて皆がそれぞれ自分に合ったものを選ぶことができる健全な世界となっている >>231
いくらでもあるから探してみ
>>237
お前がtauriに関するレスをしたところにお前が勝手にレスしてきて「tauriの話はしていない」とか言い始めただけだろ
cordovaみたいなのはPWAもちゃんと対応してるので、PWAならtauri関係ないというのも違う
unsafeもやはりお前なのか。。。お前が分かってないだけ >>239
Rustで31%とれそうな奴あるんか?
仮にあったとしてもそもそもRustのほうが圧倒的に人口少ないんやからJSの31%と同じコミュニティ規模出そうと思うと全然足らんぞ ってかJSが覇権とった時ってHTML上書きとJQuery以外あったん? ないわけじゃなかったけど、猫も杓子もjQuery一色だったな 当時jQueryはブラウザ間の違いを吸収する役割を担ってたからというのもあるけど そもそもなんでWebフレームワークとして生き残れるかどうかって話になってるんだ?
Rustの本分はWebで言えばrustlsとかquicheみたいな最下層のライブラリ実装にあるんでは…
まぁWebフレームワークやGUIで普及するのはきついと思うよ >>229
>Rustが件の調査で1番だったのはGCランタイムとか関係なく、安全で速いと嘯かれた人が騙されて使用してるだけ
デタラメすぎてあまりにも酷い
Rustを使っている人は騙されているのかw
>実際には苦労して書いても速くなく、
苦労して書くという時点でプログラミング初心者か
普通に書けば速いぞ
>unsafeを使って初めて速くなるか、
unsafeは閉じ込めた中で使うものであって普通は外でわざわざ使わん
そんなことしなくても速い
>回りくどい方法を使わないと普通に書くより遅くなる
回りくどい方法で速くなるなんて見たことも聞いたこともない
普通に素直に書けばコンパイラの最適化で十分に速い >>245
Rustはそんな下層だけの狭い対象の言語ではない
最近はサーバーサイドで起きるWebレンダリング同一コード要請から
Webフレームワークの一定数はRustがシェアを獲得するのは間違いない >>249
まぁGAFAやベンチャーの採用で1-2%くらい取れる可能性は否定しないけど
現状の大半を占めるJS/Java/Rubyあたりからの移行は無理だと思うけどなぁ >>247
騙されてるだけ
Rustをunsafeなしに書いたらC/C++より速くなる道理がない
制約を課している分必要メモリ量も増え、その分の時間がロスに繋がる
JIT込みで動作するVM系言語でもGC走る間もなく終わってしまう大半の簡単な処理では差などつかず、場合により簡単に抜かれてしまう
>>249
きついっつーの
JavaScriptでひぃひぃ言ってる大半のプログラマが使いにくいと思わないはずがなく、十分なメリットがないためにシェアが上がらない
全てをストリームで処理したい世界線に移動しないと無理 >>251
質問
ではなぜJavaからC#やGoに至るまで
各種ベンチマークでRustが圧勝しているの? >>240
自分の頭が悪くて普通に書いたら遅くなるコードがどういうものなのか想像もできないので
検索キーワードだけでも良いので教えてください >>252
ベンチマークは極端な仮定に基づき簡単に特性を見るもので実運用ではその通りにはならないのが通例
依存する全クレート含めてRustの外へのアクセスを除いてunsafeを全く使わないコードで動かしてみればいい
>>253
Rust >>257
コードを見てみましたが失格
fnの前にunsafeを付けなければなりません
かなり酷い初心者のようですが出直して勉強してからまた来てください playgroundは初心者さんが使いそうなので、あんまり変なので負荷をかけたくないってことで、compiler explorerにしてみた
https://godbolt.org/z/MEqoTM5Yq どうでもいいけど compiler explorer よく見たらvimが使えるw ちょっと感動したw >>257
普通に書いたら遅くなるコード例が欲しかったんですがこれは何をしようとしていて何が遅くなっているんですか? >>262
お前が誰かなんて知らねーし、すでに自分で探せと言ったものを何度も他人に聞くなよw 本当に頭悪いなw おれのコードか? 欲しけりゃくれてやるぜ… 探してみろ この世の全てをそこに置いてきた(ドン >>263
どの書き込みに対するレスかすら確認せずに反論してたのか...すごい レスは適当に追うけど、長すぎんだよw
複数に答えてるところで分岐があるんだし、かなり前のお前のレスを読まないと分からない内容にしてるお前の頭が悪いだけw
しかも断られた内容を「自分の頭が悪くて...どういうものなのか想像もできないので...だけでも良いので教えてください」と懇願するほどの馬鹿w
再度断られると煽りはじめ、しかもしつこく深夜まで…やばいってお前w >>266
うんうん、わかったわかった
「普通に書いたら遅くなるコード例」はあなたからは出てこないのね
それならこれ以上やりとりしてもお互い無益なのでやめましょう
何度もレスさせてごめんね
こんな遅くまで付き合ってくれてありがとう >>267
はじめに断ってんだろw 二度断ってなお煽ってきて何いってんの?w 確信犯がそれで許されるわけねーだろw
二度と書き込みませんと宣言したら許してやるw 名だたる企業がRustについての肯定的なレポートを出しているが、それも誤りだというのか?
誤りではないが、だからといってシェアがとれるわけではないというのか? 特定のシチュエーションで肯定的という事実だけ
それを元に何かを想像するのは自由だが、どの領域でどこまでシェアを伸ばせるかについては想像に過ぎない
さも名だたる企業が領域とシェアについて言及してるかのごとくに言い広めるのは良くない 自分で見つけられない人は可哀想w どこまでも煽っていくスタイルなんですねw >>270
名だたる企業が安全だと言っている事実に誤りはないのかね?
速度もCと互角と言っているのは? C#ってWindows限定じゃなきゃ選択肢に上らない。いつMSがやーめた、今度はこっちにするわって言い出すかわからんもん。Rustはどうかな? MSがやめたら進化は止まるかもしれんが使えなくなるわけじゃないだろ 言語に関してはMSはディスコンしてもサポートがめちゃ長いから比較的安心
D言語みたいなのでもまだ続いてるからRustも今のところ心配する必要ない
衰退し始めたら気長に移行すればいい >>274
昼過ぎに起きて一斉に書き込んでるね
よー寝るやつだw >>279
だなー、他のスレにも同じ時間帯に書くからわかりやすいわ 非同期関数(非同期タスク)について質問です
単純に読むとか書くとかなどは非同期関数を呼んで待たされる(=待たせてくれる)のでawaitで待てばよいのですが
何かある仕事を専門にする人がシングルトン的に存在していてそこへ仕事を依頼して非同期に結果が出たら結果をもらう場合は
Rustではどうするのが効率がいいのでしょうか?
例えばコールバックをしてもらうとか
チャネルをもらってその読み出しで待つとか
スケジューラーの中で寝て待って起こしてもらうとか
その他など各々の可能不可能とメリットデメリットと具体的な方法が知りたいです
それに加えてタイムアウト付きで結果がまだ出ずとも時間内に戻りたい場合はどうなりますか? 必要な機能をもった非同期ランタイムを選択する。
自分でやるなら unsafe でやることになるだろうけど本当にしんどい道のりになると思う。 ちょっと前提が異なるけど参考情報
hyperの中核となっているService traitは非同期コールバック方式
これでサーバーもクライアントもDNS解決もコネクション張るのも全てやっている 例えばhyperでサーバーがHTTPリクエスト受けるのにも二段のimpl Serviceが使われていて
一段目はコネクションが張られる毎
二段目はそのkeepaliveで複数回になりうるHTTPリクエスト毎
>>285
タイムアウトはその合成でいけるね 古き良きselectを使わないやつはunsafeにまみれるがいい!
$ cargo geiger // こんな人向けの話
#[tokio::main]
async fn main() {
async {
println!("{}", "こんにちは世界!");
}.await;
} だけど今さらJavaを選択しないだろ。終わりの始まりはOracleがSUN Microsystemsを買収したとき。 >>202
補完の効かないHTMLモドキ書くの辛ぽよな
VDOM系ならsauronがmacro以外でも書ける
個人的にはSilkenwebかな >>289
世の中web系ベンチャーばかりじゃないので… >>289
もちろん今となってはJavaを使う意義は全く無いが
Javaしか使えない(人材しかいない)遅れたところも存在している >>281
結局どこかで同期(待ち合わせ)したいならば
(1) 条件を満たしたらReadyになる自作Future<Output=T>を受け取りfuture.awaitで待つ
(2) lockされた非同期Arc<Mutex<T>>を受け取りmutex.lock().awaitで待つ
(3) 非同期channel::Receiver<T>を受け取りreceiver.recv().awaitで待つ
これらawaitの前の部分はfutureなのでタイムアウト付きにしたいなら
非同期timeout(duration, future).awaitで待つ または非同期sleepを使って
futures::future::select(future, sleep(duration))で任意の仕様で作成可
さらに多くのfutureが関係するならselect_all 悩ましいのが非同期処理待ち合わせにおけるタイムアウトしたときなどのキャンセル処理だな unsafeに屈してtokio/mioベースでウェーイし、二度と安全などと申しません!するのが普通
これは踏み絵なのだ >>294
タイムアウトもしくは多数のfutureから先着一択した場合でも
残りのfutureは手元に残るしその出自も把握しているわけだから
用途ごとに必要なキャンセル処理を用意したり実施したりすればよいだけ
これは非同期でなく同期で全体の処理時間にタイムアウトを設けた場合でも起きる話 async/awaitなどを使わないとしても、その手の処理を実装するなら通常は非同期I/Oを使用する
もしくは同期I/Oを別スレッドから強引にclose/shutdownする
なので、非同期I/Oを使用せずに綺麗に実装するなら、常に終わるまで待つか、キャンセル自体、つまりタイムアウトを諦めるのが普通
だから非同期を使うのであれば速度優先unsafe党に入り、RustはC/C++よりちょっと遅く、C/C++同様安全でない言語です!と懺悔しながら他の言語に許しを乞う必要があるw >>298
プログラミングしたことないためにunsafeが何かをわかっていない人だ
わかってないからブレて毎回主張に自己矛盾 >>301
そんな単純な煽りはつまらんから
もっともらしいデタラメ並べた長文よろ このスレ以外でも思うんだけど
言語アンチって何が目的なの?
嫌なら使わなきゃいいだけだし
他に良い言語があると思うならそれ使えばいいじゃない
特にrust使う人なんてほぼ他の言語経験者なんだし
適材適所で使う言語選んでるでしょ
わざわざこのスレに来てrust批判したり他言語マンセーしたりしたとこで
大半の人は必要なら使うし必要ないなら使わない
余りにも不毛だからそういうのやめて欲しいわ 俺はRustの話しかしてないんだがw
君もRustを使ってunsafe党に入るのだwwww
viva! cargo-geiger!!!!! >>303
反応を楽しんでるんだよ
それでリアルの憂さを晴らしてる # ようこそ!unsafe党へ!
cargo install cargo-edit cargo-geiger
cargo new notsafe
cd notsafe
cargo add --features full tokio
cat >src/main.rs <<EOF
#[tokio::main]
async fn main() { async { println!("{}", "こんにちは世界!"); }.await; }
EOF
cargo run
cargo geiger geigerは依存ライブラリを含めたunsafeの使用状況を集計するツールらしい
unsafe党とか言ってる人はもしかしたら
「見えないところでunsafe使うならRustは安全アピールするな」って言いたいのかもしれないし
unsafeをカウントできることがRustの安全性のひとつであることを知らないのかもしれない Unsafe使うなら見えないところでやってくれ。そしてUnsafe由来のバグは出すなっていうのがRustの思想ちゃうん?
ツール使わんと見えないなら大成功では # 見えないところでunsafeで一旦実行できるも、ちょっと修正するとコアダンプの例w 修正はunsafeでない場所w
cargo install cargo-edit cargo-geiger
cargo new --lib maybe_safe
cd maybe_safe
cat >src/lib.rs <<EOF
pub fn read_address_4byte(address: usize) -> i32 { unsafe { *(address as *const i32) } }
EOF
cargo build
cd ..
cargo new perfectly_safe
cd perfectly_safe
cargo add --path ../maybe_safe maybe_safe
cat >src/main.rs <<EOF
#![forbid(unsafe_code)]
fn main() { maybe_safe::read_address_4byte(&0 as *const i32 as usize); }
EOF
cargo geiger
cargo run
cat >src/main.rs <<EOF
#![forbid(unsafe_code)]
fn main() { maybe_safe::read_address_4byte(0); }
EOF
cargo geiger
cargo run >>312
これ何でread_address_4byteにunsafeつけないで内部でunsafeブロック使ったの?
渡された数値を無条件にアドレス扱いしてそこにアクセスするのが絶対に安全だと判断した根拠を
コメントで書いといた方がいいよ
ちゃんと理由を説明できないならunsafeブロック使うのはやめたほうがいい そりゃ変なプロパガンダかまされて、こんなしょーもない言語使わされるなんてことになったら最悪だからな。
若いバカに騙されるバカ経営陣によくある話だわ。 バグを混入させたくて混入させる人は原則いないのである。
例示は可能な限り単純化しているが、現実世界は複雑なのだ。
プログラマが「意図せず」混入させてしまうバグを「一部」言語で回避できるからこその「安全」であり、プログラマ自身が安全性を保証する側になってしまってはもはや「安全とは言えない」w
処理系が「標準」として提供するものは処理系が「安全」を保証するものと仮定して除外し、「標準以外」の安全性を確認できればプログラム全体の「安全」も仮定でき、それを機械的に可能にしているのがRustという言語w
そしてそのする「標準以外」の安全性を確認ツールがガイガー(geiger)なのだw
「標準」が「安全」と仮定される限り、ガイガーがunsafeをscanした結果☢ が1つもなければ、プログラム全体の「安全」も仮定されることになる。
もし☢があるならば、プログラム全体の「安全」は言語(処理系)でなくプログラマ自身が保証する必要がある。
この☢がある状態はC/C++と何ら変わらず、かなりのライブラリで☢が氾濫する昨今、言語が保証する「安全」についてRustに優位性は存在しない。
に依存する。
Rustコミュニティは他言語と比べれば豆粒程度なので、言語が保証する「安全」がプログラム全体の「安全」に占めるウェイトが大きくなければ、どこかで破綻し見限られ、喧伝してる手前凋落する運命となるだろうw
しかしそれでも人は速度を諦められず、unsafe党に次々ダイブしていくわけであるw
☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢
☢ガイガーカウンター=放射線測定器☢
☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢☢ unsafeじゃなくて、carefulってキーワードにすれば良かったのにね わかってる人しか使っちゃいけないんだし、unsafeのほうがいいかなあ libcがunsafeだからlibcの利用禁止!!!!!!!!!!!!!!!!!!!! exampleが日本語のクレートなtrie木を使おうとしたらもうコレw
https://i.imgur.com/ksKY9gX.png
こういうのばっかりなんですわ > 例示は可能な限り単純化しているが、現実世界は複雑なのだ。
それはまあその通りで、だからあんまり複雑な内容をunsafe内で書くのはやめような unsafe使ってるのは競プロの異常者たちだけというデータは出てるから無視で良い cargo install でコマンドをインストールすると依存するクレートも含めて
$HOME/.cargo/bin/registry
以下のディレクトリにソースや管理用のデータが格納されているようですが、
これらの管理というのはどのようにすればよいものなのでしょうか?
一定以上に古いものを削除するとか、
インストール済みのバイナリクレートが依存しているものだけを残すとか、
そういう機能は普通はあるだろうと思うのですが cargo のコマンドとしては見当たらず、
何か専用のコマンドを入れる必要があったりするのなら教えて欲しいです。 単純なものの組み合わせで複雑になるのだよw
複雑になると人間的なチェックでは見落としが出るのだよw
その際にどこまで複雑になっても正確さ100%の機械的チェックは申し分なく有効なのだよw
それを(Rustの)内側だけにある要因だけで捨ててunsafe党に入ってしまうのが現状のRust w
私もあなたもunsafe! viva! unsafe! Rust is unsafe!!! >>327
組み合わせる前にunsafeブロック閉じよう
unsafe内で組み合わせ爆発を起こすな😡 最新ナンバリングスレをワッチョイ化しないと多分だめ >>329
コンパイラチェック可能な最小限のunsafeブロックの外側が、事実上安全ではないんだよw
これをどこまで広げるかを人間が決めるのでは、複雑な現実世界に適用した際バグると言っているw
誰もがこれなら平気!バグはないというところから、バグは生まれるわけだw
unsafeがあるだけでそれは致命的な障害となるw viva! unsafe! Rust is unsafe! そう、つまりRustはおおよそのケースでC/C++と同じくらい安全でなく、RustはC/C++より少し遅い言語なわけだw
viva! ☢unsafe☢! Rust is ☢unsafe☢! 銀の弾丸はないんだよ
だけど物事は少しずつよくなっいくの そのとおり!今は嘘をつかず謙虚にユーザーが増えるのを待っていろw
非同期に必要なlibc周りのゴミゴミした部分が十二分に安定して標準に取り込まれれば逆転も可能だろw
それまではジッと我慢w ここで真っ赤になってディスろうがRustの利用は拡大している Google Trendsのen-USで見たらRustでプログラミング言語がないんだがw
https://i.imgur.com/Gi5avJg.png >>328
ありがとう
しばらくこれで運用してみる Rustは何かにつけて長時間ビルドする上にそのサイズがクソデカイから困るんだよなw
容量足りなくていつも消して回り、ちょっと変更してフルビルドっていう繰り返しw >>341
適当なテストでリリースしたりしませんw まず言語と関係なく一般的な前提として
・プログラミングをする上で当然unsafeな操作を避けることはできない
・unsafeな操作を組み合わせることで安全なプログラムを作ることがプログラミングの本質
次に
・unsafeな操作のコードは人間による厳重なチェックが必須でこれを避けることは出来ない
・unsafeな操作がプログラム全体に散らばってしまっているのがCとC++
そこでRustの方針
・unsafeな操作は局所的に閉じ込めてしまい安全なインタフェースを公開
・そのunsafeな操作で作られた安全なインタフェースの安全性は人間が保証
・データ競合を含めたプログラム全体の安全性はRustの言語ルールによりコンパイラが保証
したがってどんなにプログラムとその中のデータや依存関係が複雑化および巨大化しようとも
Rustにおいて人間は局所的に閉じ込めたunsafeな操作部分のみ厳重チェックすればよくなった
暴れている ID:JmzvOlHn はこれを理解することが出来ない愚かな存在
例えば >>312の read_address_4byte()
これはunsafeな操作を使ったunsafeな関数であるからunsafeを宣言しなければならない
>>330
ワッチョイ化しなくても愚かな存在はすぐに区別がつくので大丈夫
並行してワッチョイ無しスレも立って過疎と活性の結果となる >>343
> ・unsafeな操作を組み合わせることで安全なプログラムを作ることがプログラミングの本質
これ嘘w
> ・unsafeな操作は局所的に閉じ込めてしまい安全なインタフェースを公開
これ「局所的に閉じ込め」られると思ってるところがただの思いこみw
理由は
> ・そのunsafeな操作で作られた安全なインタフェースの安全性は人間が保証
これが不可能だからw
閉じ込められないと、
> ・データ競合を含めたプログラム全体の安全性はRustの言語ルールによりコンパイラが保証
これの意味がなくなるw
という説明を長々としてきたのだが、残念ながらID:Bj7uYOrmには理解が及ばなかった模様w
以上から、Rust is ☢ UNSAFE ☢! となるw
どうして理解できないんだろうなぁw
機械は言われたとおりのことしかできないけど、言われたとおりに100%ミスなくできるw
でも人間は必ずミスをするんだよw
保証できていることの意味が全然違うことを理解してほしいねw スレの途中で作ると人移動しないかもしれない。いやでも、おじさんこんだけ激しく荒らしてるから、移動するかもしれない。 この手の嵐はワッチョイ導入でさぁーっと消えるw
そらもう面白いように消える不思議なことに 少なくとも自演はできないし一週間NGできるから快適になるよなぁ どうぞどうぞご自由にw 自演なんてしてないし、別IDなんてないけどなw
そもそもまともな内容書いてないやつしかワッチョイの話してないのが非常に胡散臭いw >>344
そうは言ってもデバッグするときunsafeな場所が限定されている方が良くない? >>351
設計意図が実装に見えるのは大事なことw
でもそれを安全というのはちょっとねw >>351
どうせunsafeがある時点で論外って答えが返ってくるだけだぞ >>352
safeという強い言葉が気に入らないってこと?
それはまあちょっとわかる 「大規模化/複雑化すれば人間は必ずミスをする」からこそ
それを回避するためにRustが作られた
Rustコンパイラはコードがどんなに大規模化/複雑化しても
メモリ安全性やデータ競合が無いことを保証できる
その唯一対象外となるのがunsafeな操作
Rustでは局所的な極小規模で単純な部分にunsafeな操作を閉じこめる
そして外へは安全なインタフェースのみを公開
人間にしか出来ないunsafeな操作利用の妥当性チェックを最小化することに成功した
どんなに大規模and/or複雑化してもプログラム全体の安全性を人間がチェックする必要が無くなった
一方でCやC++などはプログラム全体にunsafeな操作が散らばり人間の手に負えない
GC導入のハンデと引き換えにメモリ安全性の一部を得たGC言語であっても
ヌルポインタを含む一部のメモリ安全性やデータ競合などを防ぐことが出来ていない
それらの安全性を保証することに成功したプログラミング言語がRust 可哀想なくらいに他人の言葉を受け入れられない人だねw
Rust作られた目的まで捏造されちゃったよw
unsafeを閉じ込められるというのは幻想w
外には安全なインターフェースのみ公開という理屈が「仮定」できるのは処理系とのそこが提供する標準含むランタイムだけw
プログラマが実装するプログラムはunsafeを使った途端にプログラム全体がもうunsafeでC/C++と同じなんだよw
GCは関係ないw
リアルタイム性を予測可能にするためにランタイムが予測不可能な時間を使用することを回避したい場合のみGC有無が関係するw
null安全は書き方だけであり、他の言語でも大抵似たようなことが実現できるし、機械的なチェックも可能w
そしてC/C++と同様に安全性が保証できず、C/C++より遅い言語が何を隠そうRustさんw >>354
viva!tokio!な現状だと安全ではないと言ってるだけw
cargo geigerで☢がなければ(C/C++より)安全って言ってもいいと思う ずーっと同じこと言って人を煽ってるだけ。典型的な構ってちゃん >>356
ほら、理解できていない
unsafeで作られた安全なコードに対する人間による妥当性チェックの必要性は
それが標準であろうとデファクトであろうと自作であろうと全て同じ
逆に言えばその局所的なコードの妥当性チェックがなされていれば
Rustではプログラム全体の妥当性がコンパイル時点で保証される
Rust以外のプログラミング言語はこれができない >>359
理解できてないのはお前w
ランタイムやVMは他の言語でも別枠だからプログラム本体とは切り離して安全としていいんだよw
そこは言語が規定してる部分だからだw
C#やJavaでVMがnativeだからって文句言うアホはいないし、各種インタプリタ言語の組み込み関数が何で書かれてても誰も何も言わないだろw
RustよりはC#やJavaの方が明確に安全と言えるけどなw
Rustだと言語の内側からunsafeにしたいという欲求が生まれる温床があり、不必要にunsafeが発生しうるw もし仮にTokioが標準ライブラリならOKなのか?
標準ライブラリにバグがある確率とコンパイラにバグがある確率は同じくらいとして 標準ライブラリはもの凄い小さくて、あとは個人や小さな組織が作った野良ライブラリだよりだから、
安全性は全然担保されてないと思うがなぁ。 どの言語であれ
標準ライブラリやランタイムに問題が生じなかった言語は存在しない
だから『標準』と名が付くかどうかはどうでもよい問題
Rustにはunsafeか否かの区別があるから他の言語より遥かに良い状況
標準か否かに関係なくunsafeではないコードに対してunsafeを冠せずに出したら厳しく指摘される
そしてunsafe以外についてはコンパイラが通れば安全性が保証される でかい標準ライブラリを許容してると、言語をメンテしてる人たちにとっては切り捨てもできず、互換性を担保するのとかでどんどん負担もでかくなるし、言語自体の進歩まで遅くなりうるよ
Goの進歩がやたら遅いのも、もしかしたらそういうとこにも原因あるかもね しかし非標準で同じようなライブラリが乱立してるような状況では新規言語に飛びつきたい言語オタクの精神異常者以外には参入し辛い状況ではある
普通の人普通の企業にとってはGoの方が魅力的に映るだろうな
進歩が遅いのも一度勉強した知識がそのまま使い続けられるし一度書いたコードが使い続けられるってことだし >>365
逆でしょ
RustはGoogle含めた大手IT企業から全面支持
そしてRustは後方互換性も維持しているから2018editionと2021でもほとんど変わらない
安心して導入できる
そして一番重要な言語機能
Goは今年ようやくジェネリクスだけど期待外れ
イテレータ導入提案すら何度も却下
GoとRustどちらも書ける人なら確実にRustを選ぶ現実 >>366
Googleなんて言語オタクの精神異常者集めた企業の代表じゃん。そりゃそうなるよ。Common Lispとか好きそう
ジェネリクスとかイテレーターがなくてガッカリしてるのも言語オタクの特徴だな。普通の人はそれでいいって思ってるよ ほんとこのおじさん言語叩けりゃ何でも良いんだな。今度の棒はGoか。んでまだCommonLispのこと根に持ってる。そしてホントは.NET好きなのは隠しきれてない 標準ライブラリならOKだよ
入っていると入っていないでは雲泥の差がある
処理系が責任を持って開発する部分で、基本部分である以上、ユーザーが少なくてもunsafeでも最大限の品質が保証されるから
言語仕様開発や処理系側からすれば、そんなところを大きくすると言語自体が保証する安全性にケチがつきかねないから小さくしたい心情はあると思う
純粋にフットプリントは小さくしたいしね
ただスレッドや同期機構まで用意してるので、世の流れとして非同期くらいまでは標準にしないと扱いにくいとは思う
切り離しやすく決まってると嬉しい
他の言語との比較はRust自体の説明に必要でない限りこのスレではしない なんだ、コード見て技術的なこと話してたらな、て思って見に来たら、
他のスレと同じで言語があーだこーだ言ってるだけか
まあ5chはこんなもんか unsafeがあるからダメなんじゃない
unsefeじゃないところがsafeなのがRustの大発明 曖昧な感想をダラダラ書くより、これを紹介したほうが有意義だろ。
安全と危険のご紹介
ttps://doc.rust-jp.rs/rust-nomicon-ja/meet-safe-and-unsafe.html とりあえず英語版の方が内容新しいんで、こちらへ
https://doc.rust-lang.org/nomicon/working-with-unsafe.html
このexampleの2番目の
if idx <= arr.len() {
なんかが典型的で、これ気付けません。直後にあるとおり、
”...This program is now unsound, Safe Rust can cause Undefined Behavior, and yet we only modified safe code. This is the fundamental problem of safety: it's non-local. The soundness of our unsafe operations necessarily depends on the state established by otherwise "safe" operations...."
なわけ。
テキストでは最終的に可視性を利用して局所化してみたいなハウツーを入れてるけど、それは対策方法であって、局所化できる保証はない。
人間にミスは必ずあるからね。
どう書けば安全か分かっていて、それを確実に守れるなら、人間はC/C++でもバグ1つなく完璧にコーディング出来るはずなんだよ。
ってわけで、Rust is ☢UNSAFE☢ !!!! >>373
紹介している内容と主張している内容が一致していないように思えますが
unsafeが一つでもあればunsafeだと主張してるのかな? >>374
unsafeに閉じ込めるのはプログラマの責任、ということだろ。
Rustがunsafe以外で未定義動作にならないことを保証しているんだっけ? Haskellに対してモナドで副作用してるから純粋関数型言語じゃねえって感じの主張してはるんやろ モナドが副作用起こしてるんじゃなくて実装系が副作用起こしてるんだけどね。
まああの辺の無駄な解釈学振り回すことばっかりな点は同じクソさを感じるわな。 言語の理屈の立て方とそれの実現の仕方はレイヤが違う話だし、
言語の話をする以上は言語の理屈を軸にするしかしょうがないじゃん。 >>373
unsafeを用いて安全なコードを書いている部分に対してのみ
人間が注力することができるようになったRustは他の言語より進んでると理解できた?
>>375
unsafe以外ではRustは未定義動作(undefined behavior)がないことを保証
>>379
そこは理屈というか理論というか抽象的な概念で理解しておくべきところだね
実装や内部表現は変わりうるし最適化で消滅しうるので実現方法で理解しようとしても不安定で無意味 >>380
何度言っても「unsafeを用いて安全なコードを書いている部分」が人間には限定できないのを理解できてないのはお前w >>367
Goが魅力的と書いておいてGoogleをそこまで叩くちぐはぐさ
Rustを叩ければ棍棒は何でもいいんだな
>>381
まだ意味不明なこと言ってRust叩きしてるのか
敗北を認められなくて引くに引けずかね >>382
叩く・叩かないや敵味方のような二つでしか考えられないのか? >>382
論理的に反論されたことがないという認識なんだがw
上から頭ごなしにこうです!と言われて、いやこうこうこういう理由でそうとは思えないと伝えたら、
「意味不明」とか「Rust叩き」とか、「敗北を認められな」いと言われて議論が終わっちゃうだけw >>383
自分が何を書き込みしたのか見直そうぜ
>>365
>>普通の人普通の企業にとってはGoの方が魅力的に映るだろうな
>>367
>>Googleなんて言語オタクの精神異常者集めた企業の代表じゃん >>385
叩いてみんなに構ってほしいだけなんだかほっとけ >>384
Rustの言語ルール及びunsafeとそれ以外(safe)を分けることで
初めてコンパイラが通れば安全性を保証すること成功した枠組みを
未だに理解できずイチャモンつけるだけしか出来なくて恥ずかしくないのかね? >>388
別にunsafe自体はRustが作ったわけじゃないよw
C#が大昔にunmagedなコードを呼び出すために開発した
Rust同様に別にどこまでも範囲は広げられる
Javaもnativeってあるよね
この2つは基本的にVMが保証している枠組みを外れる部分に対して使用されてるので、VM内のコードが実行される限り、使う動機が発生しない
対してRustは安全を担保するための所有権の仕組みを逃れるためなど、unsafeを使用する動機がいたるところにある
標準が提供しているライブラリが足りないこともあり、これは相当深刻な状況なわけだw
すると、両者が意味するunsafeな部分の意味が大きく変わってくる。
簡単に言えば原則safeな部分を書き換えるためにunsafeが使用されないかどうかの違いw
残念ながらRustは安全を担保するための所有権の仕組みを逃れるためなどの理由でsafeな部分を書き換えるためにunsafeが使用されてしまっている
Rustがunsafeな理由の1つはこの動機の部分に潜在的な問題があるってことw unsafeの話はマジで意味不明なイチャモンでしかないな
25860の方がよっぽどやべえだろっていう >>389
Rustはデータ競合やメモリの安全性を保証する
しかしJavaもC#も保証することはできず無関係
Rustよりも優れたプログラミング言語を持ってこないとこの件でRustを批判するのは無理 >>389
tokioやmioがunsafe使ってるのは所有権の仕組みを逃れることが主な理由だと思っている? unsafeはなければ未定義動作が発生しないと仮定できるw
RustだけでなくVMで動いてるものは当然メモリ安全だって仮定できるw
Rustの場合は特性としてnativeであり所有権に制限を付けることで、パフォーマンスへの影響が少ない形で安全を仮定でき、さらにデータ競合がないことも仮定できるのが有利なところw
ただ、unsafeがあるだけでそこは無制限に全て瓦解してしまうんだよねw
そして付けた制限に対する回避のためにunsafeを使用するという潜在的な問題があり、さらに標準の機能不足により、unsafe増加が加速し、収拾がつかない大☢UNSAFE☢時代に突入しているわけだw
Rust is ☢UNSAFE☢! おーまいが! Rustが安全だというなら、cargo geigerで☢がない状態にしてから言ってくださいねw cargo geigerの存在がRustがベターであることを証明してて笑える そういうのは他の言語なら機能性だけで分かるし、nativeならnativeで閉じてるから安心できるんですよね
でも何度も言うようにRustは何をしなくとも自らunsafeを入れてしまうので調べないと分からないw
しかも使い方的にその場所だけに閉じないため、☢UNSAFE☢を実感できてしまうとw ついにただ煽るだけの人まで現れたw これがRust品質w どのレスを指してるのか知らんが、俺を指して言ってるなら人違いw
ってか煽ってるだけで何もできなそうな奴多すぎw
芸風とかどうでもいいし、それを気にするならお前の芸風がキモいだけw 人を煽るくせに自分が煽られるとすぐ被害者面するの、かまってちゃんおじさんの平常運転です ID変えて大変だねw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 流そうとして必死なのはお前w 俺はもう飽きてるぞw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 飽きすぎたわw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 荒らしにとって一番辛いのは叩かれることじゃなくて無視されること
NGにすればいいけど、もっといいのは違うかまってちゃんを全員が構うようになるとそうとう辛いw 荒らしじゃないんだよなぁ・・・俺だけだよ。本当にRustの話してるのw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 > もっといいのは違うかまってちゃんを
複製おじですか もう20レスくらい俺以外Rustのラの字もないなw
ワッチョイ入れてもねぇw NGとかなかなかしないんよねw しかも俺結構大手のプロバイダだから多分被るよw
俺には関係ないからどうでもいいけどw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 ワッチョイなんて俺には何の関係もないんだがw
俺が言うのもなんなんだが、Rustに関係のない話はやめた方がええでw
現状Rustというゴミ言語は俺にすら有効性を認めさせられないってことで、世間に広まるのは夢のまた夢なんだよなぁ・・・
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 Rustが一部の高齢(脳年齢)エンジニアを狂わせるunsafeな言語であることが示されつつあるな
Rustがunsafeなのか高齢エンジニアがunsafeなのかは意見が分かれそうだが導入するときは要注意かもしれない 裏ではtokio使って、非同期でも何でも簡単に使えます!安全です!とか他スレでホラ吹きまくってるからだろw
嘘をついてまで他スレに喧伝までしてなければ誰も叩いたりはしない
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 実際はRust以外がunsafeで、Rustは一部safeなところがあるだけだけどね
高齢者はみんなcでunsafeに慣れてるから、Rust使わんでもunsafeだよ rustだけやってりゃいいとか言ってる奴は100%老害化するよ。 Rust以外がunsafeは嘘w C/C++などの古い言語は全部unsafe w
ただRustもunsafeな領域を人間には確実に限定できないので、☢があれば実質全部unsafe w
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 >>420
無知すぎるな
geigerは標準ライブラリを調べていない
そしてRustの標準ライブラリの中はもちろんunsafeだらけ
それなのにgeigerは一番肝心な標準ライブラリを調べていない
それはなぜか?
unsafeの正しい使用には全く問題がないからだ
unsafeを使ってそれを内部に閉じ込めて外部に安全なインタフェースのみ提供する
標準ライブラリを含めてライブラリはこの安全なインタフェースを提供している >>421
> geigerは標準ライブラリを調べていない
そんなことは>>316で書いたw
>>356 >>369でも言ってるとおり、ランタイム/VM+標準ライブラリは「前提として」100%信用するw
この境界は区別しないとプログラム全体の安全性が定義できないし、それらの実装言語は何でもアリだからw rustは "安全な言語" じゃなくて "比較的安全なシステムプログラミング言語" だよ
議論のポイントがずれている unsafeを混在させたくないなら自分で書けばいいだけだよ
その選択ができることが他所とは違うところ >>422
愚かだな
どのプログラミング言語においても標準ライブラリに問題が発見されて修整されてが繰り返されてきた
標準ライブラリとなっけられているからといって100%信用できるわけがない
そこには何も保証がない
一方でRustならば標準か否かに関係なく保証ができる
unsafeを利用して安全なインタフェースを作った部分のみ人間がチェックすればライブラリ全体の安全性はRustの言語が保証できる
Rust以外の言語はライブラリ全体を人間がチェックしなければならない
Rustがこの点で全ての言語に対して優れていることは誰の目にも明らかだ で、おまえその優れた言語で何か書いてんの?え?actixのサーバー?コマンドラインのプログラム?(笑) >>423
ずらしてるんだけどねw
>>424
残念ながら世の中の需要はそうなっていないから、>>335と言ってたわけだよw
分離できる言語は多いけどw
>>425
そこを保証するのは処理系側なんて、その言語の利用者側は100%信用するしかないんだよw
標準以外がunsafeを利用してたらもう終了w なんで理解できないのかなw
>>426
匿名掲示板でそういうのは聞かないだろ普通w お前が言ったらじっくりいろいろ聞いてやるよ(俺は言わないw) >>426
主要基本orミドルの書き換え
今はLi*uxというあるOSを全てRustで書き直すプロジェクトの統括責任者兼主席ブログラマやってます >>429
そっちは読んでもいねーよw 俺宛て以外読みたくないだろ面倒だからw
まあ返事はしなくても分かると思うけどw ヨシッ!!
#![forbid(unsafe_code)]
fn main() { maybe_safe::read_address_4byte(0); }
※全文は>>321 参照 >>434
その>>312を見たが作った関数がunsafeなのにunsafe宣言をしていない
ルールを守らずにunsafeを使用してはいけない
ルールもわからない初心者ならばunsafeを使うな >>435
前にも同じこと言われて
>>314
>>316
となり、以降まともな反論ないんだけどw
しかもこのやり取り何度目?wwww #![forbid(unsafe_code)]
fn main() { maybe_safe::read_address_4byte(0); }
(unsafeじゃないから)ヨシッ
∧ /ヽ
// ̄ ̄\|
∠_╋__〉
/ @八@ ヽ _
工ニf(_人_)エ二|′)ヽ
\ヽヽノノ ノ ヘ |
⊂⌒)_>―――′イ (_)
`ー、_ノ/ ̄ヽ |
_|| | |
( 人_ノ Λ
\ス ̄ ̄レ-Λ \
( ̄ ) / / \ノ\
 ̄ ̄ ( ヽ \_)
\ノ
※全文は>>312参照 だから、比較的安全、ということでいいでしょ
オフィシャルも含めてそれはみな承知のことだよ 比較的安全という「希望的推測ができる」だけで、実際にはC/C++と全く変わらないw
前にも言ったけど、ミニマムなunsafe領域を含む「設計意図としてのunsafe」が示せるだけw 全く変わらないというのは、同じものを同じ人がCとRustで書いたとき、問題が起きる確率は変わらないだろうということ? >>440
違いを理解しよう
C/C++では安全性の保証は無し
ライブラリ含めて全てのプログラムに対して相互に関係する影響について人間が全てチェックしなければならない
Rustでは言語がすなわちコンパイラが安全性の保証をすることができる
unsafeを使った部分のみその影響範囲が閉じていることを人間がチェックするだけでよい 作り方の問題で言語の理解がしっかりしてればどちらも同じように出来るw
機械的な保証があるかないかが問題で、その分はunsafeがある時点で保証できなくなるだけw
ただし、Rustには作り方に制限があるため、その作法でC/C++が実装された場合の話にはなる、というだけの話w
C/C++で作法を守らない部分の責任は人間側で負う必要があるw
C/C++とRustどちらも保証はできないw Unsafe使ってたらSafeじゃない理論ってC#でもFFI使ってたらUnsafeってことでいいの? C#はunmanagedなコード以外でunsafeを使用する動機がないので懸念点がない上に、外部の何かへのアクセスが前提で、managedなオブジェクトの書き換えはあまり発生しない。
例外的にmanagedなオブジェクトを書き換える場合でも、unmanagedコードがロジック自体を持たないのが普通。
他方Rustは所有権の制限を適用しない目的などでオブジェクトを書き換えるため、それ自体がロジックの一部となっている。
例えば他のライブラリやシステムコールを利用してるなど、明確に分かるものがあればまだいいが、そういうのがないただのデータ構造に対するロジックなどにもunsafeが適用されるため、利用者側からは想定すらできず、それらを発見するためのツールが必要になってる状況も踏まえ、事態は深刻である。
そして多すぎるunsafeのせいで、それらを利用者側が正確に分類・把握できない、もしくは気付いてすらいないのが現状w
実験室向けの簡単なコードならそれでよくとも、製品レベルのコードでそれは致命的であるため、安易な「安全宣言」は悲劇しか生まないw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 C#はFFI使わなくてもぬるぽ(ぬるり?)できるから最初からunsafeかと
せぐふぉじゃなければセーフというなら話は別だけど
Rustはunsafeな範囲を可視化できてその範囲指定が正しいことを機械的に保証できるから
C/C++に比べて比較的安全(安全性を担保しやすい)って話なんだけど
0か100でしか考えない人間にはこの差が見えないのかもしれないな 「Rustはunsafeな範囲を可視化できてその範囲指定が正しいことを機械的に保証でき」ないのですよw
機械的に保証できるのは俺の言い方だとミニマムな部分だけw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 変な言い回しするから言いたいことがよく分からない
自分でunsafe書いてなくても、依存関係がunsafeを濫用してたらアプリケーション全体としてはunsafeじゃないか
という主張なんだよねたぶん 俺の主張の大事な点は2つだよ
・安全とするにはunsafeと宣言すべき関数を機械的に決めることが出来ない
・安全のために所有権に厳しい制約を課しているが、その厳しさからunsafeを使う動機が常に言語内にある
これらから導かれる推測は多岐にわたるけど、分かりやすい結論として
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀
という警鐘を鳴らしているだけw 一つ目言ってる意味がもう分からないんだけど
普通に言ってくれ わっチョイの議論が出てるけど個人的には過疎るから賛成できない
この人は語尾wでNGすればいいだけと思う >>450
普通に言った。何が分からないのか言ってくれw 安全のために所有権に厳しい制約を課しているが、その厳しさからunsafeを使う動機が常に言語内にある
わからんでもないかもしれん >・安全とするにはunsafeと宣言すべき関数を機械的に決めることが出来ない
安全とするには〜する必要がある
なら分かるが、
安全とするには〜出来ない
なので主張がわからんという話でしょ >>448
『自分でunsafe書いてなくても、依存関係がunsafeを濫用してたらアプリケーション全体としてはunsafeじゃないか
という主張』は
実際に使われているモジュールでそういう例があるならば成り立つ
しかし現実にはunsafeなモジュールは存在しなくて
>>445はその例を挙げることすら出来ていない
机上の空論を繰り返しているのみ >>453
その場合ですらunsafeは使っても構わない
そのunsafeを使った局所的な部分に影響が閉じ込められていて安全なインタフェースのみ公開されていればよい
そしてRustコンパイラは残り全体の安全性を保証できる いい加減無視することを覚えとけ
こんなの相手にするから調子乗るんだぞ >>454
(安全とするにはunsafeと宣言すべき関数)を機械的に決めることが出来ない
こう書けば分かるのだろうかwwww
>>455
issueがないとでも思ってるの?wwww
>>456
「そのunsafeを使った局所的な部分に影響が閉じ込められてい」る前提がおかしいw
安全なインタフェースとは誰が判断するの?wwww
どうなってたら安全なの?wwww
それを人間が判断する以上、どこまでも間違いは起きるよw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 反応してるやつも同レベルの荒らしだから、いっしょくたにあぼーんしましょうね >>451
これが正解
末尾wは煽りたいだけだから対話する気がないし 例えばTokioを使ってUnsafe由来の変な落ち方する例とかが有ればUnsafe使ったライブラリ全然信頼できねーなって同意すると思う 与えられたコードがunsafeかどうかを判定するルーチンHがあればいいんだろ >>461
https://www.google.com/search?q=tokio+issue+unsafe
全部調べてないと証明できないのであればあるw
これ以外に存在しないかどうかは不明だが、お前が信用するしないで事実が変わるわけじゃないw
>>462
そうだね
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 次スレはワッチョイつけますから覚悟しておいてください
それまでの命だ
せいぜい楽しむがいい >>463
読んでみました
・質問者がunsafeの言葉を使い間違えてました
・ランタイムを何度も複数回スタートさせていました (そしてunsafeな状況は起きていない)
などで
(unsafeを使って)安全でないインタフェースを公開してしまったわけではないようです
>>464
反対です
過疎ってRustが不利になるだけなので
皆がワッチョイ無しスレも立てる結果となるでしょう スレの終わりに切り替えて結構すんなりワッチョイスレに移行できたスレ多いよ。途中でもうまくいくかはよくわからん。
何れにせよ、スレが機能してないよりは過疎のほうがマシだな 変化が多い言語でデファクトも定まってないし、ワッチョイ付けてもたぶん過疎らないと思うけどな そもそもみんなまともにrustの話をしたいのに
おじさんが関係ない自演で横から茶々入れるから
みんなめんどくさくなっていなくなるのよ
その自覚はある? ワッチョイスレはもうあるぞ
ここからさらにワッチョイスレ作っても分岐して打ち捨てられたワッチョイスレが増えていくだから先にこっち消費してくれ
https://mevius.5ch.net/test/read.cgi/tech/1532697692/ >>465
質問者?issueで質問者って何の話してんだよw
全部読んで少なくともその中にないことを証明するんだぞw
どこを読んでそう書いてあったのかすらないのでは、証明にはならないw
約 567,000 件あるけどなw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 今回のやつはずっと同じIDの上に
文面から即NGできるにもかかわらずしつこく構ったやつらが悪い
反省しろ かつて自治厨と言われた俺の手腕を発揮してやるよ
最近はそこまでの情熱は無くなったが去年あたりからrust始めたからまともに議論したいのよ 荒らされるよりは過疎るほうがマシ
ワッチョイひとつでこの手合はピターッと来なくなるから そう思うならさっさとワッチョイスレ立てればいいじゃん
なんでやらないの? ワッチョイ有りRustスレは既に>>470にあるので使い分ければよい
ここはワッチョイ無しRustスレなので次スレもワッチョイ無しで行く
両方あれば全員に不満はない 使ってないスレを再使用するのはスレを無駄にしないという点では有意なんだけど、勢いもスレ順も変だから人はあんまり来ないのよね。で、何も知らずに来た人が荒らしにかまってしまう。
何れにせよ15がワッチョイ無しというのはありえない選択肢。 >>477
ここはワッチョイ無しRustスレの系統
だからここの次スレはワッチョイ無しで確定している
ワッチョイ有りRustスレは立てられても放置されるという歴史がある
再び放置スレを増やすようなことをしてはいけない
以下に現存するワッチョイ有りRustスレがある
プログラミング言語 Rust 4【ワッチョイ】
https://mevius.5ch.net/test/read.cgi/tech/1514107621/
Rust part6【ワッチョイ】
https://mevius.5ch.net/test/read.cgi/tech/1532697692/ 自分たちが他スレ嵐てんのに自分たちにワッチョイ付ける訳ない。己のやってることを顧みろ >>477
そう思うならワッチョイスレ盛り上げろよ
せめてpart6埋めてからワッチョイpart7を立てて盛り上げる方向にしろよ 「荒らされるよりは過疎るほうがマシ」って言いながらこのスレに書き込んでワッチョイpart6使ってないのってどういうことなの そんなにワッチョイが嫌なんだね。じゃあ次スレはワッチョイ有りにしよう。別にデメリット殆ど無いし。 それ語尾wがワッチョイなし立ててそっちが盛り上がって使われないワッチョイpart15が打ち捨てられる未来しか見えない >>483
ワッチョイ有りRustスレは既に2つもある >>478
ここワッチョイ無しRustスレの次スレはもちろんワッチョイ無し
両方あれば全員に不満はない >>486
やってみてもいいけどワッチョイなしが過疎ったら責任とって埋めろよ >>487
ワッチョイなしじゃなくてワッチョイありざ過疎ったらの間違い 次スレ自体はどうするん?
>>980 が新規で立てるか >>980付近で既存スレの古いスレに誘導するのか ここワッチョイ無しRustスレはいつも通り
ワッチョイ無しで次スレを立てることになる
ワッチョイ有りRustスレは既に2つある>>478
両方あれば全員に不満はない よしでは方針を発表しよう
そのワッチョイありスレはおじさんが謎にageてるから
いまだに存在しているものと認識している
つまり既に侵食済みなので捨てる
Part15からワッチョイありスレとして継続していく
異論がなければこれで行く 確かによく見たら4は腐ってるな
でも6は使えるだろ。使ってくれ それはワッチョイに効果がないことを示してるだけでは
報復のような行動や分断を産む議論は思う壺だと思う
黙ってNGに放り込めばいい そもそもワッチョイにデメリットは無くてメリットだけなんだからカジュアルに入れればいいじゃん。
一人だけ急にここはワッチョイ無しスレの系譜なんて言い出した人もいるけど。そんな系譜無いし。 デメリットはどうせ分裂してワッチョイ15という過疎放置スレが無駄に出来ることだけなので、そうなった時にちゃんと埋めてくれるならなんのデメリットもない ワッチョイ必要だと思うならごちゃごちゃ言わずにさっさと自分で立てろよ
スレ立てくらい出来るだろ ワッチョイだから過疎ったんじゃなくてスレを複数作ったから過疎ったってことよ
スレを使い分けようって時点で問題児だらけデース!ってアピールしてるよ
今回のunsafeおじさんが暴れてた頃に誰もワッチョイスレに誘導しなかったところを見ると、存在すら忘れてたんじゃないか?
https://mevius.5ch.net/test/read.cgi/tech/1532697692
↑火種になりそうな人、話題は全部ワッチョイに誘導しようね。火種に触る人もワッチョイに行こうね タイトルが同じだと数字が小さいスレに人がよりつかないのは当然なので
質スレと議論スレにでも分割して議論スレをワッチョイスレとして新たに始めればいいんじゃない?
議論したいってことみたいだから
誰も立てないからここ2回連続してスレ立てたけど
立てたらワッチョイガーとか繰り返し言われるのはさすがに腹が立つよ
問題は荒らしを相手にしてる人たちなのに ま、次スレからワッチョイでいいやん
荒らし目的の人はサヨナラしてくれていいやん
スレがノイズまみれになるのは目が滑ってしんどい 強引な変更には断固反対
少なくとも現状のワッチョイなしのスレも残すべき >>500
せやなー、次からワッチョイありで
>>501
荒らしたいの? 別にワッチョイにしたかったら両方作ればええやんw
俺は両方に反応するからw
ワッチョイなら一週間はNG設定変えなくていいんじゃないのw
ただ被るやついても俺のせいにするなよw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 この程度の勢いのスレではそう簡単にワッチョイ被らない いや・・・前1日で4人被ってたぞ俺にw 割と人の多い地域で割と大手のプロバイダだから被りやすいんだw
まあ俺は言ったからなw
Run cargo-geiger!
💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 どうでもええよ
今後もワッチョイの無いスレに書き込むし
スレが無ければワッチョイ無しで立てるから ワッチョイスレの方が過疎化して完走できないことになると誰でも予想できる rustならわっちょいつける方がらしくはあるな。言語思想がそういう感じだし。 Linux環境のrustでkbhit関数(キーイベントの取得)ってありますでしょうか?
コンソールアプリ(ゲーム)を作ときに使用しようと思ってまして 真面目な質問はワッチョイありに書き込んでワッチョイ無しスレから誘導すればいいよ。
ワッチョイ無しスレは過疎らないし、ワッチョイスレは荒らしNGできるし文句言うやつは荒らし以外おるまい。
スレの再利用もできるしな。 https://tech.aptpod.co.jp/entry/2021/12/03/070000
これとかそれっぽい?
でもcratesはそれっぽい名前の奴ほど放置ライブラリという特長があるから正直調べ方がわからん Linuxでコンソールアプリだとncursesが思い浮かぶ
Rustでは使ったことないけど
https://crates.io/crates/ncurses # 俺様はcrosstermに一票w
cargo install cargo-edit cargo-geiger
cargo new crossterm_example
cd crossterm_example
cargo add crossterm
cat >src/main.rs <<EOF
use std::time::Duration;
use crossterm::event::{poll, read, Event, KeyCode};
use crossterm::terminal::{enable_raw_mode, disable_raw_mode};
use std::io::Error;
fn main() -> Result<(), Error> {
enable_raw_mode()?;
loop {
if poll(Duration::from_millis(1_000))? {
let event = read()?;
println!("Event::{:?}\r", event);
if event == Event::Key(KeyCode::Esc.into()) {
break;
}
} else {
println!(".\r");
}
}
disable_raw_mode()
}
EOF
cargo build
cargo run
cargo geiger
# Run cargo-geiger!
# 💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 >>511
Rustで書いてもstdinへの設定自体は他の言語の時と全く同じ
以下C言語風でRust的に書けるnixクレート使用
まずstdinがエコーされたり改行まで入力されないのを解除
let mut stdin = stdin();
let mut termios = tcgetattr(stdin.as_raw_fd())?;
termios.local_flags &= !(LocalFlags::ECHO | LocalFlags::ICANON);
tcsetattr(stdin.as_raw_fd(), SetArg::TCSANOW, &termios)?;
これでstdin.read()で1文字ずつ入力キーを得られる
次に入力がない時にブロックされないように設定
let mode = fcntl(stdin.as_raw_fd(), FcntlArg::F_GETFL)?;
let mode = OFlag::from_bits_truncate(mode);
fcntl(stdin.as_raw_fd(), FcntlArg::F_SETFL(mode | OFlag::O_NONBLOCK))?;
これで入力がなくてもstdin.read()がすぐに返ってくる
あとは自分の好きな仕様で例えば
let mut input = [0; 1];
let code = match stdin.read(&mut input) {
Ok(_) => Some(input[0]),
Err(ref err) if err.kind() == ErrorKind::WouldBlock => None,
Err(err) => Err(err)?,
};
これで入力ASCIIコードがOptionで得られる
他にも例えば非同期とチャネルを使ってインタフェースを洗練して
ノンブロッキングにせずともread()とチャネルへのsend()を繰り返す
というキー入力専用の非同期タスクを作って
使う側ではチャネルからpoll_recv()で入力があるか見るとか
あるいはそもそも入力なしという状態を得る必要がないならば
その非同期タスクでread()がある度に指定クロージャを呼び出すなど ちなみにstdinからのASCIIコード取得では不満で
もっとrawレベルのイベントが欲しいならば
libevdevをRustで扱えるevdev-rsを使う regex crateの問題って
外部ユーザー入力の正規表現をパースして使っていた時に
めっちゃ複雑な正規表現だとDoS攻撃になっちゃう恐れがあったという話か よほどのことがない限り
外部のユーザに正規表現を入力してもらうケースは無さそうだよな >>521
rustのregexってNFAベースなんだっけ? iteratorのメソッドのnthってどういう意味?なんかの略? 1st, 2nd 3rd, 4th, 5th, 6th, ..., Nth ←コレw
# Run cargo-geiger!
# 💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 いやいやいやいやいやいやいやいやいやいや
うそやろ?だまされないぞ!( `・ω・´) 起源は何かなEmacs Lispにもあるし相当古そう
(nth N LIST)
Return the Nth element of LIST. N counts from zero. If LIST is not that long, nil is returned. 色んな言語で使われている
Lispでnthはリストのn番目を返す
C++でstd::nth_elementはn番目を基準とする並べ替え
CSSで:nth-child()はn番目を選択
など nthの起源はプログラミングじゃなくて数学かなー
数学用語としてOxford Dictionaryとかにも掲載されてる
https://www.lexico.com/en/definition/nth と思ったけど、辞書の意味とはちょっと違うかな・・・ nthでもgetでもいいけど、添え字で取得するのは無理なんだよね? 定数時間でアクセスできないものに添え字を使うのは紛らわしいからやってないのでは
あとイテレータの場合nextが&mut selfを要求するのでIndexは実装できないし
IndexMutを実装するにしても0..n番目の要素をconsumeするから添え字のセマンティクスに合わないと思う コストが高かったり危険だったりするものは字面の上でも目立って欲しいしな。 iteratorは原則順次アクセスだから、原則ランダムアクセスな添字は一般的ではないw
何でも聞いてしまう子は想像力がやや不足しているw
# Run cargo-geiger!
# 💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 >>527
arity (アリティ; 引数の個数) も unary とか binary の -ary を名詞化したものダゾ >>532
自由に添え字でアクセスしたい時はcollect()する
もちろんcollectはその分のコストがかかるけど他の言語では常にそのコストを強制されてるのだから
もし必要ならばRustでもそのコストを払えばよい >>532
昔は RandomAccessIterator があったけど unstable のまま rust 1.2.0 で deprecate されたみたい
https://doc.rust-lang.org/1.3.0/std/iter/trait.RandomAccessIterator.html
> trait has not proven itself as a widely useful abstraction for iterators, and more time may be needed for iteration on the design
C++やDには random access iterator はあるけど、 rust では今のところ必要ないという判断みたい >>538
それは内部でメモ化のコストを払うだけだからね
どうしても残したいならtake/take_while等してcollectでもいい
一方でnthはメモ化コストゼロ >>539
RandomAccessIteratorはslice::Iterなどランダムアクセスできるイテレーターに実装されてるトレイトなのでメモ化のコスト云々は関係ないよ >>537
ヒープ確保と解放はコスト高いけど
定数もしくは上限Nがある時は
collect::<ArrayVec<_,N>>()でスタックに確保できる ある型 T がトレイト A とトレイト B を実装していることという制約はたとえば以下のように書けますが、
struct Foo<T: A + B> {
state: T
}
ここで T がトレイト C を実装して「いない」という制約を付ける (C を実装していたらコンパイルエラーにする) 方法はありますか? 直接的にトレイトが実装されていないことを指定することは出来ないようですが
optin_builtin_traits を使えば表現は出来そうですね。
Rust ユーザー向けのドキュメントが見つからないんですがこれって stable なんですかね? まだこうだな
#![feature(negative_impls)]
#![feature(auto_traits)] 始めたばっかでよくわかんないんだけど、https://docs.rsって公式か何かのまともなサイトなの?
10進数の小数が使いたくてhttps://docs.rs/rust_decimal/latest/rust_decimal/#これ見てたんだけど、sourceってところ押したらよくわからんものが表示されてしまう・・・・ >>546
https://www.rust-lang.org/governance/teams/dev-tools#docs-rs
ここにあるとおりrustの開発元でメンテされてる
よくわからんものがどんなものなのかよくわからないけど、マクロやderiveで生成されたコードのソースは変な場所が表示されることはあるかも docs.rsは公式サイトだけど内容はオープンソースで登録されたソースコード(コメント)から
機械的に生成してるだけだからちゃんとしてるとは限らない
sourceは生成元のソースコードのリンクになってて説明が分からんかったらソース読めってスタンス 始めたばっかでよくわかんないんだけど、ちょっとコードを書いただけで.unwrap()だらけになってしまう
もう、3行に1つは.unwrap()、ひどいと1行に3箇所ぐらい.unwap()だ
素人目に見ても流石におかしいように見えるも、解決法がよくわからないぜ .unwrap()ってさっきまで沢山打ってたのに、1箇所打ち間違ったぜ まずはif let試してみたら?
if let Ok(v) = r {v使ったほにゃらら}
if let Some(v) = o {v使ったほにゃらら} >>549
エラーなどの分岐が発生しうる時に
必ず正常値だと確信できる場合、もしくは、正常値でなければpanic終了してよい場合に
unwrap()を用いる
逆に言えば上記の場合でなければ
unwrap()を用いてはいけない
エラーなどの有無による分岐処理が必要とされている場面なのだから
if letやmatchや?オペレータ(=エラー時に即return)を用いなければならない >>549
そのコードを晒せば識者が添削してくれるんじゃね? rustでCのライブラリラップしてるけどまじでわからんこと起こりまくってて泣きそう
構造体に保持したはずのハンドラが不可解なタイミングで消えてつらい
Cにも疎いからしんどすぎる >>554
それはさすがにCでのメモリ管理とRustでのメモリ管理とそれらの違いを把握できていることが最低条件 このスレに識者がいるという錯覚wwww
# Run cargo-geiger!
# 💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 >>556
C/C++/Rustスレでも次世代言語Rustスレでも暴れ回って嫌われてるようですねガイガーくん
ここRust本スレには来ないでもらえますか? >>553
それがいいね
対処方法はコード次第だから一部でも晒さないと一般的なアドバイスに留まってしまう >>559
うまくラッピングしてあってもCライブラリの内部の参照とかのあたりがうまくRustの所有権システムに乗らなくてしんどいことが多々あるから仕方ないことな気がする ハンドラのトラブルで思い浮かぶのはDropで解放する機能を実装したのにCopy可能になってるケースかな
数値型で表現される場合が多いからCopy不可の型で包まないとCopy先で解放されたりして事故りやすい
基本的にDropトレイトとCopyトレイトを混ぜるのはNG >>561
CopyとDropの両立は出来なくなっているのでその問題は発生しない
https://doc.rust-lang.org/std/ops/trait.Drop.html#copy-and-drop-are-exclusive
| [Copy and Drop are exclusive]
| You cannot implement both Copy and Drop on the same type. >>557
え?なんで?w
# Run cargo-geiger!
# 💀💀💀☢☢☢☢💀💀💀 !!!! Rust is ☢UNSAFE☢ !!!! 💀💀💀☢☢☢☢💀💀💀 >>565
マクロはわかんなかった、ありがとう!
ゆっくり調べてくる! こういうのがエラーになるんだが、なんで?
エラーメッセージは Sized が満たされてないとか出るんだけど
dyn とか Box ってこういう使い方をするもんじゃないの?
let mut foo = Box::<dyn Fn() -> usize>::new(|| 1);
foo = Box::<dyn Fn() -> usize>::new(|| 2); >>56
現状のrustではBox::newの引数に渡すのはコンパイル時にサイズが決まる型でないといけないから
dyn Fn() -> usize 型の値は渡せない
以下みたいに Box::new() で作った Box<T> 型の値を Box<dyn ...> にキャストするとやりたいことできると思う
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e02762a4d2df4aed2c5396251cd0a07c let mut foo: Box<dyn Fn() -> usize> = Box::new(|| 1);
foo = Box::new(|| 2);
// ↓ このケースならばFn()使わずともfn()で行ける
let mut foo: Box<fn() -> usize> = Box::new(|| 1);
foo = Box::new(|| 2);
// ↓ さらにBoxも不要となる
let mut foo: fn() -> usize = || 1;
foo = || 2; unwrapじゃなく;がunwrapの代わりになったらよかったのに、構文解析に;なんてもう使ってないでしょうに >>572
なぜ?
>>552にもあるけどunwrapなんて非常に特殊な時のみ使うもの
論理的にNoneやErrではないと保証できる場合は使うべきだが頻度も限られる
残りはNoneやErrの時にpanic終了という簡易エラー処理の場合でしかunwrapは使われない
その簡易エラー処理をしたい場合でも?オペレータでエラーを最上位に集めて1カ所だけエラー表示を設けるとpanic unwrapを無くせる >>572
文は式と区別するため必ず「;」を伴う
例えば関数やブロックの最後(=「}」の直前)に
「;」があると文となり返り値が()となる
「;」がないとその式の値が返り値となる
そしてブロックやif-elseやloopはその値の式なので文を形成する最後に登場する時は「}」の直後に「;」が来る
このように他のプログラミング言語とは異なりRustでは「;」の存在は重要である ブロックの最後の式がブロックの評価値になるのはRubyもそうだよ
だからと言って;にunwrap割り当てろとは思わないけど unwrap はそれなりに目立つべきだろう。
一文字でどうにかするのはよろしくない。 unwrap連打することもあるんだからないな
他の言語みたいにunwrapを!で書けるようにするほうがマシ むしろunwrap_or_dieとかにして欲しいくらいだな 使いにくく書きにくくさせることで
馬鹿に知らず識らずマナーを強いてるんだよ
だからJavaでアクセッサ書くのダルいと怒ってるのと
rustでmutってタイプするのダルいと怒ってるのと
unwrapってタイプするのダルいと怒ってるのと
言ってる人はみなおなじバカ
ちなみに馬鹿に迎合してプロパティを準備してみせたウルトラバカ言語がC# だったらfnなんて短さ、どうなん?とは思うけどな。 unwrap()は論理的に安全に剥がせると明確になる特殊な場合のみ使うべきもの
見てすぐ明確でない時はコメントを付けること推奨 エラーメッセージ中で便宜上のライフタイム (?) として '1 というのが出てくることがあるけど、
これは一個目の引数のライフタイムという解釈でいいのかな? unwrap()はリリースビルドでコンパイルエラーにして欲しい
Elmみたいにデバッグビルドでのみ使えるって感じで >>585
論理的に剥がして安全なことをコンパイラが追いかけてくれるならそれもありだけど
現状で全面unwrap禁止は無理 書き捨てのコードでいちいち例外処理書かされるの面倒だからunwrapは必要 unwrap を排除したらそれぞれで unwrap みたいなものを定義して使うようになっちゃうのがオチだよ。 >>583
コメントつけるならexpectでpanic時メッセージ出した方が良いのでは >>590
論理的に起きない場合にexpectは単なるコードの無駄
エラー発生時にパニック終了していいプログラムで補完エラーメッセージとしてexpectを使う >>591
趣味の問題な気がするけどその理屈だと論理的に起きない場合はコメントの無駄とならない?
それともコミュニティーで広く普及してる慣例があるのかしら 一般的に、論理的に正しいがコードを見てすぐに把握できない可能性がある場合は、コメントを付ける慣例 >>591
コードの無駄というのは正確には何が無駄なのだろう
文字列分の領域? >>575
Null条件演算子とか他言語には一般的になって来てるけど、ライブラリでしかないはずのOption,Resultが言語の中核みたいになってるRustが
採用するとは思えない。Option条件演算子? 他でのNull合体演算子つまりNull時にデフォルト値とする演算はRustではunwrap_or
もちろんそれら他の言語ではT型そのものにNullがありミスを防げないが
RustではT型とOption<T>型に分かれているためミスが起きない いや言語的な特性のこと言ってるわけじゃねーからwいちいち知識疲労で解説しなくていいからw >>596
rust の場合 try {} 構文が対応するものかな
try { a?.b?.c }
みたいに書ける >>600
try構文使わずとも書けるよね
fn main() {
let a = Some([[1, 11], [2, 22], [3, 33]]);
let x = (|| Some(a?.last()?.first()? * 100))();
assert_eq!(x, Some(300));
} >>596が言ってるのはnull条件演算子
>>597が言ってるのはnull合体演算子
そりゃ話が通じるわけない >>597
C#とかSwiftとかKotlinとかNull safetyを備えてる言語も勉強してね
ちょっと恥ずかしいよ >>601
なるほど、クロージャにすれば?使えるって発想なかったわ stableでどうしてもtryっぽく書きたい場合の苦肉の策でしかないな クロージャ(ラムダ)の即時実行は他の色々な言語でも行なう頻出パターン
Rustでは他にもforやwhileから値を返したい時などにもクロージャの即時実行で行なう これって、公開するメソッドのの数だけディスパッチャメソッドが増えてく感じなの?
https://tourofrust.com/81_ja.html
結構めんどくさいような気もするんだけど・・・・こういうのってエディタの拡張とかが勝手やってくれたりとか、支援みたいなのあるの??? >>608
プログラマーは全く何もしなくてよい
dyn Traitの場合はメソッド数分の関数ポインタを持つディスパッチ用テーブルが各使用型毎に自動的に生成されて実行時に自動的に適用される
impl Traitの場合は使用メソッドの関数がモノモーフィゼーションすなわち各使用型毎にコンパイル時に展開される
逆にプログラマーが自分で分岐処理する第三の方法としてenumに各使用形を収容してmatchによる分岐処理があってこの方法が有利になるケースもある C++ だと静的な多相はテンプレートで、動的な多相は仮想関数 (抽象クラス) でやってるわけだけど、
Rust だと dyn だけで切り替えられるってわけだな。 >>608
tour of rustでRustに入門するのはやめたほうがいいぞ
中身が更新されてないしGoと違ってtourから始めるのは害にしかならないから わかる。
Rust の型システム・所有権システムは理屈が分かってないと慣れでどうにかなるもんではない。
理解した上でなら手を動かしてみるのは悪くないと思うけど。 >>612
それはどんな言語も多かれ少なかれありそう
Cのポインタもそうだしね >>607
クロージャの即時呼び出しは基本的に言語機能が足りない場合のワークアラウンドでしょ クロージャは引数と戻り値を推論してくれるからこそだね
関数でも、なんかの条件付きでもいいから推論してほしいわ 関数含むモジュールレベル定義の型推論はやろうと思えばできるけど
コンパイル時間への影響がでかいのと、ドキュメント的な意味で型を書いた方がわかりやすいという理由で
敢えて対応していないとどこかで読んだ気がする
とはいえ戻り値のimpl Traitは制限された形での型推論と言えるんじゃないかな >>614
Rustでは型指定しなくて済む利点もあるしクロージャと関数の使い分けの一種じゃないかな
もちろん今回のケースはreturn値を取る別種のブロックがあれば済むけども
それをわざわざ導入しなくてもクロージャ即時呼び出しで十分 Rustのコンパイルの遅さは型推論とかじゃなく、cargoという非常に悪い仕組みのせい そんなことないよ
cargo build --timings いいね OnceCell<T> って &'static T が取れるわけじゃないんですのん? まちがえた
× OnceCell<T>
○ const Lazy<T> getでOption<&T>が取れる
初期化してなければNone LazyならDerefを適用させて使う
*lazyで&Tや&mut T https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=22ed821be70a494615ca8a661e98b78f
ごめんこういうこと
実際使ってるとき&'staticが取れないのが原因だと思ってそう書いちゃったけど違う原因かもしれないです プログラム開始時点での有効性を保証できないから何となくだけどコンパイラの事情で無理そう
&'staticって↓みたいな使い方もできるからLazyだとBの参照先が初期化済みか分からない
static A: u32 = 0;
static B: &'static u32 = &A; nightlyのstd::lazy::Lazyではなく
stableでも使えるonce_cellを使用
そのコードと同じ例がこれで動く
use once_cell::sync::Lazy;
static LAZY: Lazy<i32> = Lazy::new(|| 92);
fn main() {
let a: &'static i32 = sub();
println!("{}", *a);
}
fn sub() -> &'static i32 {
&*LAZY
} あーなるほど
なぜか'staticでmutableなのがstatic、immutableなのがconstと勘違いしてました
constって使用の度に式展開するやつだったんですね
temporary valueなんて無いじゃんとか無限に悩んでた
ありがとうございます >>630
constはコンパイル時点で定まる定数 こんな事も分からない触ってるだけで偉いと勘違いするゴミ言語 >>613
プログラムのポインタ(メモリアドレスを参照するもの)は
ポインタのメタファだから元のポインタを知ってれば理解できるが、
substructural type systemはtype systemの一種でtype systemは
型理論を元にした体系的な理屈だから理屈が理解できなきゃ理解できないから全く別の話。
>>612の言う「慣れでどうにかなるもんではない」っていうのはつまり、
わかった気になってなんとなくで書いてるやつはまだ理解してないって話でしょ。 ソフトウエアを書くにはカテゴリー論から勉強しろということかな? >「慣れでどうにかなるもんではない」っていうのはつまり、
>わかった気になってなんとなくで書いてるやつはまだ理解してないって話でしょ。
全然違う。
型システムより先に文章を理解する訓練をした方がいいぞ。 >>612
他の言語と同様にRustもそんな難しいことしていないから大丈夫
論理とメタ的な考え、例えば高階やジェネリクス等、ができる普通の人ならばRustの理解は容易い >>637
さすがにそれを「普通の人」というのは無謀。 100点オジサンや複製オジサンみたいな自分は理解してるつもりの勘違いさんが一番迷惑 >>638
普通のプログラマーなら他の言語でクロージャ(ラムダ等)くらいはさすがに使ったことあるから高階は大丈夫なはず
ジェネリクスもスクリプト言語などの動的型付け言語なら計らずともそのままジェネリックな関数となってる
そこでRustでのみ必要となる概念はそのジェネリックな関数内を安全な操作とするためのトレイト境界の指定
これはコンパイラがエラーとして教えてくれるため指定を忘れることがない
だから普通のプログラマーなら大丈夫じゃないかな 相変わらず複製おじさんは不勉強でキツイな
「普通の人」は他の言語でジェネリック使ったことあるからこんな恥ずかしい長文を書かない そうでなくRustではtrait境界が足りなければコンパイルエラーで指摘されるからスクリプト言語から来た人でも困らないって話やろ そんなことよりこのエラーの意味を教えてくれ
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=21cdaa3e90ffdd6a5ef2e06302afe03b >>641
Rust特有の話については触れたくないんだろ
理解してないから >>640
「クロージャ(ラムダ等)くらいはさすがに使ったことある」からといって「論理とメタ的な考え……ができる」ではないことは論理的に明らか。
全然論理的な考えができていない>640自身が反証になっているね。 >>643
lifetime mismatchのエラーが分かりにくければ、lifetimeを省略せずに明記して確認すればいい あと#![feature(nll)]でビルドしても分かるはず >>646
むしろ論理とメタわからんプログラマーは言語関係なく向いてないっす 理解の程度を0か1で考える人は底辺プログラマーに向いてる 所有権でよくわからないって言えばさあ
fn asdf() -> &str{
let s = "jkl";
s
}
みたいにした時に、関数を抜ける際にstrのライフタイムが尽きちゃう訳じゃない
でも逆になぜ&strしかないのに、どうして関数を抜けるところまでstrのライフタイムが持つのか?そこら辺がよくわからねえな
&strを通じてstrを所有できているのであれば、&strをリターンできても良いような気もするのに・・・・どうなってんの? >>651
fn asdf() -> &str
は
fn asdf<'a>() ->&'a str
のようにlifetimeを省略した記法なんだけど、
この 'a は引数にも現れないし何の寿命に対応するか分からないからエラーになっちゃう
今回の文字列リテラルみたいにプログラム開始から終了まで存在するデータへの参照なら、
プログラム開始から終了までを意味する 'static を使うことはできる
fn asdf() -> &'static str
また以下のように引数に参照が登場する場合は、
戻り値の寿命は暗黙的に引数と同じだと見なされる
fn asdf(a: &str) -> &str
は
fn asdf<'a>(a: &'a str) -> &'a str
となるということ
この辺の仕組みは lifetime elision でググると情報出てくるよ >>647
>>648
両方やってみて結局こうなったがまだよく分からん
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=aafabd8057a50f537f9ff410c03461d2
yが借用中にもかかわらずdropされたというふうに読めるけど、f(&mut y)が終わった時点で借用も終わってるから問題無いのでは?
でも試しにこの後yをどうこうするコード付け足してみると、どうも借用しっぱなしになってるっぽいエラーばっかり出るのよな >>651
&’static strが返されてるからだよ
リテラルはstatic扱いだと思っておけばいい
>>652
fn asdf<'a>() ->&'a strと書いても’>>651のケースはエラーにならないよ >>654
エラーにならないのか
その場合 'a は何に推論されるの? ありがとう!
なんかちょっとズレたエラーメッセージだなと思っても、省略・推論されているなんて夢にも思わなかったから意味がわんなかったぜ! >>658
もてるよ
https://ideone.com/ZMCl2R
fn main() {
let a = 1;
let b = 2;
let v = vec![&a, &b, &a, &b];
println!("{:?}", &v);
} Rust 入門者です。
全く実用的な意味はなく練習として符号無し整数を桁ごとに返すイテレータというものを考えていたのですが
同じ制約を重複して書くことになってしまい不格好な気がします。
https://ideone.com/qOmnhW
ベテランが華麗に書いたらどんな風になりますでしょうか。
それとも Rust ではこれで良いものなのでしょうか。 >>662
ありがとうございます。
たしかにこのコードではトレイト Digits にスーパートレイトを付ける必要はないですね。
想定を後出しにして誠に申し訳ないのですが、これはライブラリ (クレート) としてまとめようとしているつもりでした。
ここに書かれていない未知の型にトレイト Digits を実装することがあり得るという意味です。
問題になるのは、 Digits のスーパートレイトを消してしまうとどんな型でも Digits の実装自体は出来てしまうということです。
// ↓ Digits にスーパートレイトを付けなければこう書くこと自体は出来てしまう。 この段階でエラーになって欲しい。
struct Foo {}
impl Digits for Foo {}
そしてメソッド digits を呼出すところでエラーになります。
let bar = Foo {};
for x in bar.digits() { // ← ここでエラーになる
println!("{}", x);
}
逆に言えば digits を呼出さなければエラーになりません。
どうせ使えないことがわかっているならトレイトの impl の段階でエラーであって然るべきだという判断が
重複する制約を書いた意図です。
メソッドがイテレータを返すなんていうのはよくあることだと思うので、
いちいち重複したことを書かかなくて済むような何かがあるんじゃないか……という想像から質問した次第です。 >>663
そういう前提ならばこんな感じで impl の方の制約を T: Digits に変えるのはどうじゃろ
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6bd0ab54e4cbd88ca2a0502f9e74315d
あと T::Error: std::fmt::Debug についてはどの trait の associated type に対する制約か分かり辛いから
<T as std::convert::TryInto<u8>>::Error: std::fmt::Debug,
としても良いかもね >>664
ありがとうございます。
なんてこった! こんな単純なことでよかったとは……。 数値にメソッドを生やすメリットが思いつかないからこれだけでいいんじゃない?
fn digits<T>(n: T) -> impl Iterator<Item=T>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>
{
itertools::unfold(n, |n| (*n != T::from(0)).then(|| {
let rem = n.clone() % T::from(10);
*n /= T::from(10);
rem
}))
}
fn main() {
let foo: i64 = 9165731750932755204;
for x in digits(foo) {
println!("{x}");
}
} 実用上は関数で十分だろうけど、Rustって整数のプリミティブ型にもたくさんメソッドあるし、
メソッドを生やすのが流儀なのかな、って俺も思ってたけどどうなんやろ? >>667
過剰にトレイトを作るなというのはドキュメントのどこかに書いてあったような気がする。 >>666の関数をメソッド化しようとしたら
traitやimplの中では関数はimpl Iteratorを返せないと怒られた
この制限は将来緩和される可能性ある?
implでなく返す型を具体化したらコンパイル通って動いた
traitとimplでwhereのところが冗長な気がするけど両方とも外せない?
trait Digits<T> {
fn digits(self) -> itertools::Unfold<T, fn(&mut T) -> Option<T>>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>;
}
impl<T> Digits<T> for T {
fn digits(self: T) -> itertools::Unfold<T, fn(&mut T) -> Option<T>>
where T: Clone + PartialEq + From<u8> + std::ops::DivAssign + std::ops::Rem<Output=T>,
{
itertools::unfold(self, |n| (*n != T::from(0)).then(|| {
let rem = n.clone() % T::from(10);
*n /= T::from(10);
rem
}))
}
}
fn main() {
let foo: i64 = 9165731750932755204;
for x in foo.digits() {
println!("{x}");
}
} >>670
こんな記述もできるようになるわけね
let displayable: impl Display = "Hello, world!";
const MY_CLOSURE: impl Fn(i32) -> i32 = |x| x + 1;
let x: impl Iterator<Item = i32> = (0..100).map(|x| x * 3).filter(|x| x % 5); >>669
traitとimplのfnの型制約なくしてimplの制約にするのはどう?
Tに対する制約は実装に依るものなのでimplが課してるものとみなした方が自然な気がする >>672
具体的にはどんなコードになるのですか? >>669
>>672 の意図はこんな感じ。返り値も associated type にして実装に委ねられるようにした。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1dfdb310cd07023a69acca6cbba434ed >>674
where制約宣言の場所をメソッドfnからimplへ移動させることで結果的にtrait側で制約する必要がなくなるわけか >>674
元々の想定では符号付きの場合を型の制約で排除したいと考えていました。
トレイトが実装されているかどうかだけでは必要な性質を満たしているかどうか判定しきれないと考えて
個別に実装する必要があるという判断をした次第です。
個々に人が判断するのではなく制約で包括的に判定するとしたら std::ops::Neg を実装して「いない」という条件を付ける
必要が出てくるかと思いますが、今の Rust だとそういう制約は付けられないですよね? >>676
そこは汎用的に空のtrait Unsignedを空のimplで用意して使う
自分で用意してもいいが既にあるnum::Unsignedをトレイト境界に加えるだけで希望を叶えられる >>675
trait宣言でtrait境界制約しないメリットは他にもある
例えば文字列(例 "57261")に対するdigits()をimplできるようになってこの場合は別のtrait境界をimpl側で書くことになる
ただし別問題として現状ではまだ安定化していない2つの機能サポート待ち
1つ目はimpl Traitのspecializationでfor Tが既にあるところへfor Stringやfor &strできるようにするため
もう1つはGATs (general associated types)でイテレータで参照返しできるようにするため String の配列でパターンマッチしたいと考えていますが、
こういう書き方をすると String と &str を比較しているとして型が合いません。
fn main() {
let foo = [String::from("bar")];
let baz = match foo { ["bar"] => 1, _ => 2 };
}
かといって書けるパターンは制限があるので↓こう書くことも出来ません。
fn main() {
let foo = [String::from("bar")];
let baz = match foo { [String::from("bar")] => 1, _ => 2};
}
ガードを付けるかスライスの配列を作るかくらいしか方法はないですかね?
fn main() {
let foo = [String::from("bar")];
let baz = match foo { [ref x] if x =="bar" => 1, _ => 2 };
}
fn main() {
let foo = [String::from("bar")];
let bar = &foo.iter().map(|ref str|&str[..]).collect::<Vec<_>>()[..];
let baz = match bar { ["bar"] => 1, _ => 2 };
} >>679
配列は長さ固定
長さが異なれば別の型となる
マッチングは全て同じ型でなければならない
つまり長さ1の配列パターンがあるならば全て長さ1の配列
つまり配列としてマッチングする必要がない
実際には長い配列で先頭だけマッチングしているとしてもfoo[0].as_str()でよい
おそらく例として簡略化して書いたのだろうがもう少し具体化した方がアドバイスを受けやすい 配列を使わずにスライスを使えば可変長マッチングができる 問題はそこじゃなくて &[String] をパターンマッチする方法がないってことだよね Stringのままだと、文字列のマッチはガードでやるしかなそうだし、
その場合なら &str にしてからマッチしたほうが良さそうだね 変換するならばヒープ使わずに配列mapかな
match foo.map(String::as_str) はちょっと惜しかった 配列mapだと元のStringがdropされるから&str作れないのでは 配列mapは別の配列となる
元は消えないのでdropはされない 別の配列になるけど
mapがなぜかselfを要求する
つまりStringの配列に対して何もできない
Stringの長さの配列すら生成不可能
Copy実装型の配列に対してしかmapを使えないのではないか >>687
map が要求する self ってのはイテレータのことですよ。
配列の所有権が移ったりはしませんよ。 >>689
失礼しました。
同名のものが配列にもあるんですね。 >>687
長さの配列は元のStringへの参照を保持するわけではないから生成可能
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1389138f28b6679332ad660d8920ea5e
元のStringがconsumeされるのでStringへの参照を持つようなデータへの変換はできない
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f358e19998b508fe1955ea5274a7daf5
元の配列がdropされて良いならCopyな型に対してしか使えないということはないよ
例えば構造体の一部フィールドだけ変更するみたいな用途にも使える &strの配列に変換してから比較すると変換時と比較時とで2周するのと
比較対象がconst相当じゃないとだめなのでguardのほうがベターなケースが多いと思う 配列mapは新たな配列を作る
つまり配列map自体が元の配列をdropするわけではない
Copyを実装していない型の時はmoveとなるため結果として元の配列がdropされる
Copyを実装している型の時はmoveが起きないため元の配列もそのまま使える
// Copyを実装していない型の場合
#[derive(Debug)]
struct XM(i32);
let a1 = [XM(1), XM(2), XM(3)];
let a2 = a1.map(|XM(n)| n);
println!("{a2:?}");
// println!("{a1:?}"); // エラーとなる
// Copyを実装している型の場合
#[derive(Debug,Clone,Copy)]
struct XC(i32);
let a1 = [XC(1), XC(2), XC(3)];
let a2 = a1.map(|XC(n)| n);
println!("{a2:?}");
println!("{a1:?}"); // エラーとならず元の配列も残っている 意味不明な解説だな
「array::mapはselfを要求する」の一言で済む話だろ 配列mapは
Stringの配列を&strの配列に変換できないけど
&Stringの配列を&strの配列に変換できるよ
つまり
Stringの配列を&Stringの配列に変換できればよくてそれがeach_ref() each_ref()はまだstableじゃないので
Stringを&strにしておく方法でヒープ(Vec)を使わないならこうかな
let x: [String; 3] = ["foo".into(), "bar".into(), "baz".into()];
let y: ArrayVec<&str, 3> = x.iter().map(|s| &**s).collect();
let z = match &y[..] { ["foo", ..] => 1, _ => 2 }; こういう何がしたいのか分かりにくいだけのコードは勘弁して欲しいな iter→map→collectだけのコードが分かりにくい、って初心者でも言わないだろw
3行目の数値1と2は謎だが>>679の質問者のコードそのままだな mapの中身は(|s| s.as_str())にしたいな
初心者だけど&**sはちょっと分かりにくい そういう視点ならば
match &y[..] のところも
match y.as_slice() にする? そこまでしてやるメリットが全くない
matchでやるならマッチガード一択 >>700
sが&Stringだから
*sがStringになって
**sがstrになって【Derefによって】
&**sが&strになる
というのを知った時は衝撃的でした rustのジェネリックでSystemCみたいなのって書ける?
C#だと無理っぽいんだけど 定数パラメータなら最近サポートされた
#[derive(Debug)]
struct Matrix<const N: usize>([[f32; N]; N]);
impl<const N: usize> Matrix<N> {
fn identity() -> Self {
let mut m = Self([[0.0; N]; N]);
for i in 0..N {
m.0[i][i] = 1.0;
}
m
}
}
fn main() {
let identity: Matrix<3> = Matrix::identity();
println!("{:?}", identity);
}
ちなみに
struct Matrix<const N: usize>([f32; N*N]);
はできなかった 演算子 ? のことを個人的にトライ演算子と呼んでいたんですが、
公式には単に「operator ?」としか書いていないみたいですね。
口頭で言うときにはどういう言い方で呼びます? >>708
他は機能で名前が付いているのにそれだけ字面を元にした名前なんですね。 try-catchが将来入ることを考えると、 ? の役割は try と言うより throw 相当と考えた方が良いのかな >>709
question markそのものにYes/Noの2択を突きつける意味があるからだろうな >>711
そんな意味ないでしょ
いい呼び名が見つからないからしかたなく今の名前になってる 後置にするにしても普通のメソッドみたいになんらかの名前で呼び出すようにしたら
それがプログラムの流れを変える制御構文的なものであることが分かり難くなるだろうし、
後置の演算子という選択はとても良いと思う。 >>716
そういう点では
.awaitも記号オペレータにしてほしかったわ
良い記号さえあれば >>716
後置の演算子にするのはRustの使い方なら当然だと思うが
声に出して読めない(人によって読み方がバラバラになってる)のが問題
try file.read()時代は誰でも同じように読めた
file.read()? は読めない
.awaitはオペレータを導入したとしてもawaitオペレータという呼び方でみんな同じように読めるから何の問題もない file.read().await? よりも
file.read()待? でいいんじゃないかな
オペレータ記号は仮に「待」とした >>713
Cowにmapってどういう仕様にするの?
どちらの場合でも統一的に具体型へ変換ならcow.as_ref()かcow.into_owned()のどちらかだろうし >>722
cowを変換して何かにするのではなく
cowそのままでそれ自体を統一的に書き換えるならto_mutだね バイナリデータを受け取るいい方法ってある?
やりたいことはGETリクエストの結果送られてくるバイナリデータをファイルに保存したい
CやJavaなら適当なchar配列(Javsはbyte)でいっぱいまで受け取ってファイルに書き出すを繰り返せばいいってわかるんだけど、似たようなことをRustでやりたい >>724
Rust でも同じやで。
特に違いはない。 綺麗に抽象化したレイヤを作ろうとしたら C や Java とは違った雰囲気にはなるだろうけど、そういうのは後回しや。
綺麗だろうが汚かろうがまずはやってみたらええんや。
ところで「汚かろう」を変換したら「北中朗」と出てきた。 誰やお前は。 勉強中
Cow<T>の取りうる値は
・Cow::Borrowed(T)
・Cow::Owned(<T as ToOwned>::Owned)
とのことなので ToOwned を調べてみると
ToOwned::Owned = Borrow<T>
つまり impl Borrow<T> for S の時に
・Cow::Borrowed(T)
・Cow::Owned(S)
となる関係だと分かった
そしてこんな状況で使えるぽい
impl Borrow<[T]> for Vec<T>
impl Borrow<str> for String
impl Borrow<CStr> for CString
impl Borrow<OsStr> for OsString
impl Borrow<Path> for PathBuf 16進数文字列から整数への変換を標準ライブラリでやるにはどうすればよいですか? Cだと次のように書けるエンディアンを調べるプログラムはどう書いたらいいですか?
int x = 0x12345678;
char *p = &x;
for( int i = 0; i< sizeof(int); i++ ){
fprintf(stderr, "%X\n", *p++ );
}
CでもWarningは出ますが >>730
どうしても表示したいならば
直訳するとこんな感じ
use std::mem::size_of;
fn main() {
let x: i32 = 0x12345678;
let p = &x as *const i32 as *const u8;
for i in 0..(size_of::<i32>() as isize) {
eprintln!("{:x}", unsafe { *p.offset(i) });
}
} 原則としてはエンディアンに依存しない形で書いて入出力のときだけ from_le とか to_le とかで処理するのが良い作法だとは思うけどね……。 >>729
仕様がわからないからジェネリックにOption<T>で返すとしてこうなるのかな
stdにCheckedAddとCheckedShlがないから自作するところを略してnum::から借りた
use num::traits::{CheckedAdd, CheckedShl};
fn parse_hex<T>(s: &str) -> Option<T>
where T: From<u8> + CheckedShl + CheckedAdd
{
s.bytes()
.try_fold(T::from(0), |acc, b|
acc
.checked_shl(4)?
.checked_add(&T::from(byte_to_hex(b)?))
)
}
fn byte_to_hex(b: u8) -> Option<u8> {
if b'0' <= b && b <= b'9' {
Some(b - b'0')
} else if b'A' <= b && b <= b'F' {
Some(b - b'A' + 10)
} else if b'a' <= b && b <= b'f' {
Some(b - b'a' + 10)
} else {
None
}
}
fn main() {
assert_eq!(Some(65535), parse_hex::<u16>("ffff"));
} >>734 これ標準ライブラリにあるで
use std::usize;
fn main() {
let z = usize::from_str_radix("ffff", 16).unwrap();
assert_eq!(z, 65535);
} 現状のstr::parse()とstr::FromStr traitのコードは以下のようになっているが
fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
FromStr::from_str(self)
}
trait FromStr {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
このFromStrをAddなどと同様にOutput指定付きにしておけば良かったのではないか?
trait FromStr<Output = Self> {
type Err;
fn from_str(s: &str) -> Result<Output, Self::Err>;
}
そうすると以下のようにOutputをSelf以外でimplできるようになるから
impl<T, const N: usize> FromStr<Output = T> for Radix<T, N> { ... }
現在ある>>737のfrom_str_radix()が使えないu128出力などにも拡張できて
"ffffffffffffffff".parse::<Radix<u128, 16>>()
と使えるようになるから中途半端なfrom_str_radix()を廃止してparse()に統一できる u128でもfrom_str_radix使えるのはさておき
便利そうだけどそんなtraitにFromStrという名前が付くのは違和感あるなあ >>739
え?
例えば&strからIPv4やIPv6アドレスへの変換ですらRust標準ライブラリはFromStrを使ってるよ >>740
FromStrなのにSelf以外の型に変換されるのが違和感あるということでは T::from_str が T (Result<T, E>) 以外の型を返す関数なのは違和感あるでしょってことが言いたかった Radix<u128, 16>::from_str が Radix<u128, 16> を返してもいいだろうけど
中身はu128しかないのだから FromStr<Output = u128> で u128 を返せると便利、って話だよね
XXX::from_str の XXX 部分は文字列をどう解釈するかの指定
だから通常は Output = XXX と同一になるけど、そこを指定できると互換性を保ったまま利便性を向上できるという話だよね 提案自体は分かるけど T from str と読めるメソッドが T 以外の何者かを返すのは不適切な命名では?
別のtraitでやるべきだと思う ところでこれ書いてて気づいたけど i8::from_str_radix("80", 16) とかは PosOverflow になるんですね
16 だからできそうな気がするだけで、考えてみればそうかという感じだけど >>746
自作でもそのへんのエラーを返したい時あるけど
ParseIntErrorのnewが無い、かつ、kindがprivateなため返せなくて困ったことがある cargo が粗悪
スグにリソースを喰らい尽くす特級禍呪怨霊 >>749
メモリかCPUが足りないなら -j オプションつけるか
.cargo/config.toml の jobs 設定したら良いのでは
https://doc.rust-lang.org/cargo/reference/config.html どちらも参照で構造体のオプションをそのメンバーのオプションにするもっと短い表記ないのかな
struct1.map(|struct1| struct1.member2) メンバーを参照で返すならば
&struct1.member2 と&が必要
元のOptionのstruct1はもし参照が外側ならば
struct1.as_ref() で内側の参照にしておくことが必要 struct1.map(|struct1| &struct1.member2)
長くていいなら
struct1.and_then(|struct1| Some(&struct1.member2)) すごく曖昧な日本語だけど普通に読むなら
構造体のオプションも、そのメンバーのオプションも、どちらも参照という意味じゃないの?
struct Foo<‘a> {
bar: &’a Option<Bar>
}
↑こういう構造体を&Option<Foo>の形で受け取って内包する&Option<Bar>で返したいという話
知らんけど これならstruct1が1回しか出てこなくて短い
(|| Some(&struct1?.member2))() >>755
Option<&T>をOption<&U>にしたいだけやろ
>>751のでやりたいこと出来てるんだろうから そういうことか
だとmapするのが一番シンプル
$0やitのようなクロージャ用の暗黙的変数はないから明示的に渡すのは必須
struct1.map(|x| x.member2) 正解はこれ
try {&struct1?.member2} >>758
多段(メンバーのメンバー)を考えるとmapは見辛いし長い
なのでtryブロックもしくはstableならクロージャで?オペレータが良い >>760
tryブロックはまだしもクロージャの即時実行は意図を曖昧にするだけだから極力避けたほうがいいと思う
多段で長くなるような処理なら関数化して型を明記しておいたほうが後で楽
クロージャは型推論と外部変数のキャプチャで最初は楽できるんだけどね 十文字かそこらで終わるレベルならクロージャでも別に悪くはないと思うけどね。
多少の無駄は最適化で消えてなくなるだろうし。
ただ、そう思っていると後からごちゃごちゃ処理が増えてわけわからんようになるのが世の常というものなんや……。 多段になった時にクロージャだと「?」を重ねてすぐ書けたのですが
クロージャではなくmapを使う場合はどのように書けばいいのでしょうか?
fn main() {
struct S<'a> { o: Option<&'a str> }
let s1 = Some(S { o: Some("abc") });
let s2 = Some(S { o: Some("pq") });
let s3 = Some(S { o: None });
let s4 = None;
for s in &[s1, s2, s3, s4] {
let s = s.as_ref();
let a = (|| s?.o?.get(2..=2))();
println!("{a:?}"); // Some("c"), None, None, None
}
}
このクロージャで動いている例で教えてください >>764
それはmapじゃなくてand_thenする
let a = s.and_then(|s| s.o?.get(2..=2)); >>765
同じこと(構造体の有無)をしてるのに
さっきはmapで今回はand_thenかよ
一貫性がなくわかりにくくなってるぞ ここまで見てきて感想
// 一貫性もあり分かりやすいクロージャ
let a = (|| s?.o)()
let a = (|| s?.o?.get(2..=2))();
// 一貫性もなく分かりにくいクロージャ+α
let a = s.map(|s| s.o);
let a = s.and_then(|s| s.o?.get(2..=2)); このand_then方式が何故わかりにくくなっているかというと
let a = s.and_then(|s| s.o?.get(2..=2));
先頭のsだけを特別扱いしていることが原因
例えばこのように先頭を無条件に真となるようにすると
let a = Some(true).and_then(|_| s?.o?.get(2..=2));
その後のs?もo?も同じ扱いになり常に一貫した表記となる
上記から無駄な部分を省いてしまうと
let a = (|| s?.o?.get(2..=2))();
結局クロージャのみとなる
つまり最初の部分だけ特別扱いをやめたことで表記が一貫した >>762
それは視野が狭すぎる
クロージャ類の即時実行は他のプログラミング言語でも普通に使われる
特にRustではインライン展開されて付加コスト無し
そのため様々なcrateでクロージャの即時実行が使われている
標準ライブラリ内部では先行してtryブロックが有効となったためそちらへ移行した
つまりクロージャの即時実行で書いておけばtryブロックがstableとなった時に移行しやすいメリットもある 複オジがmapとflatMapを理解してないだけだな 標準ライブラリ内では今はtryに移行しているけど多用されているな。
激しいのだと"?"が6個も出てくる。
https://doc.rust-lang.org/src/core/iter/adapters/flatten.rs.html#322
> let upper = try { fhi?.checked_add(bhi?)?.checked_add(fixed_size.checked_mul(upper?)?)? };
これもstableでは (|| fhi?.checked_add(bhi?)?.checked_add(fixed_size.checked_mul(upper?)?))(); で動く。
したがってstableではクロージャーを即時実行する形で書き、
いずれtry_blockがstableになったらそのまま置き換えがベストな方法。 tryはクロージャ代用で困っていないが
GATsとimpl specializationを早く安定化して欲しい try blockが解決しようとしてる問題を理解すればIIFEの何が問題なのかも分かる >>779
fn main() {
let mut i = 0;
while i < 10 {
print!("{}", i);
i += 1;
}
} Rustの練習でFizzBuzzを書いてみたのですがもっと速くできますか?
fn main() {
let mut n = 1;
loop {
if n % 15 == 0 {
println!("FizzBuzz");
} else if n % 5 == 0 {
println!("Buzz");
} else if n % 3 == 0 {
println!("Fizz");
} else {
println!("{n}");
}
n = n + 1;
}
} >>776
型を指定する方法が未解決なのでいつになるかは不明
年単位で先の話になると思っておいたほうがいい FizzBuzzは単純すぎて実行時の剰余算とその分岐を避けるくらいしか改善できないんじゃないか
あとはマジックナンバーを避けて更にRustっぽく書くとこうかな
const FIZZ: usize = 3;
const BUZZ: usize = 5;
const FIZZ_BUZZ: usize = FIZZ * BUZZ;
fn main() {
(0..FIZZ_BUZZ)
.cycle()
.enumerate()
.skip(1)
.for_each(|(n, i)| match TABLE[i] {
Some(s) => println!("{s}"),
None => println!("{n}"),
})
}
type Table = [Option<&'static str>; FIZZ_BUZZ];
const TABLE: Table = make_table();
const fn make_table() -> Table {
let mut table = [None; FIZZ_BUZZ];
let mut i = 0;
while i < FIZZ_BUZZ {
table[i] = match i {
i if i % FIZZ_BUZZ == 0 => Some("FizzBuzz"),
i if i % BUZZ == 0 => Some("Buzz"),
i if i % FIZZ == 0 => Some("Fizz"),
_ => None,
};
i = i + 1;
}
table
} ダサい例として挙げられていたwhileによるカウントアップが使われているけど
const_forはまだまだ先が長そうね
そのためにはIterator
そのためにはimpl Trait >>781
https://ideone.com/QkAorv
速くはできてないと思うけど
ifじゃなくてmatchを使った例
fn main() {
for n in 1..101 {
match (n % 3, n % 5) {
(0, 0) => println!("fizzbuzz"),
(0, _) => println!("fizz"),
(_, 0) => println!("buzz"),
_ => println!("{}", n),
}
}
for n in 1..101 {
println!("{}", n.fizzbuzz())
}
}
あと下の例はenumとtraitを使ってみた
enumとtraitのほうはrustっぽく使えてるかどうか自信なし forってかなり高度な構文だよなと改めて思う
constで使えるようになるのはかなり先になりそうだな... C++ の constexpr でも for が使えるようになるまでちょっとかかったもんな。 https://ideone.com/G4kYRi
enumで持つ整数の型を固定しないようにした
最初からこうすべきだった カルビーが12月から全社員を対象にした副業制度を導入。
多様な働き方のさらなる進化を目指す
カルビー「何でもテレワーク」工場視察からゆるい勉強会まで
建設業界の常識を覆す“攻め”の働き方改革【週休3日制】を4月からトライアル導入
残業大幅減でも利益は昨対比2倍に上昇!
労働時間すべて社外勤務OK。トラック業界の“先駆者”が新制度
日野、「副業」許可制度を新設 “経験”広げて本業に生かす
ダイハツが副業容認を本格検討、その狙いと新しい働き方とは?
ダイドーグループ、「副業・副業受け入れ制度」を導入
Afterコロナ時代を生き抜くべく、ダイドードリンコが「自社人材の副業」と
「他社からの副業人材の受入れ」を開始 ふと思ったんだがそろそろブラウザ上でIDE提供増えないのかなあ >>789
i32とありジェネリックになりきってないぞ >>792
必要に応じて実装してもらえればいいかな?
impl FizzBuzz for f32 {
fn fizzbuzz(&self) -> FizzBuzzResult<&Self> {
match (self % 3.0, self % 5.0) {
(0.0, 0.0) => FizzBuzzResult::FizzBuzz,
(0.0, _) => FizzBuzzResult::Fizz,
(_, 0.0) => FizzBuzzResult::Buzz,
_ => FizzBuzzResult::Num(self),
}
}
}
fn main() {
for n in 1..101 {
println!("{}", (n as f32).fizzbuzz())
}
}
正直言うとfn fizzbuzz<T>(n: T) -> FizzBuzzResult<T>
みたいな関数を書けないかと思って先に試してみたけど
中でリテラル使って計算してるのが祟って書けなかった >>794
実装コードが異なる型は別実装でいい
しかし今回は同じ実装コードだろ
そういう時はジェネリックに書くのがRust >>795
stdだとマクロ使ってるケースが多い気がするが >>796
一般的にジェネリックにするためのトレイト境界となるパーツのトレイトは個別に型列挙してimplする必要がある
そこではマクロが有用
パーツとなるトレイトを利用してプログラミングすれば列挙の必要性がない パターンに定数を使うことは可能です。
fn baz(x : usize) -> usize {
const ZERO : usize = 0;
match x {
ZERO => 1,
_ => 2
}
}
しかしトレイト内の定数で型が確定しない状況ではそれがパターンに使える定数なのかどうかわかりません。
(のでエラーになります。)
trait foo {
const ZERO: Self;
fn bar(&self) -> usize {
match self {
Self::ZERO => 1, // エラーになる
_ => 2
}
}
}
このとき Self がパターンに現れることが出来る型であるという制限を付けることは可能ですか?
(>>794 の定数だけ impl すればメソッド自体は共通化できるかなと思って試みたけどこれをどうにもできなくて困った) >>798
その問題もTraitの関数でconstを返せないため現状では無理
だからmatchパターンでは使えないがifガードでなら使える
>>789のうちimpl FizzBuzzだけ以下に変更
use std::ops::Rem;
impl<T> FizzBuzz for T where T: Copy + From<u8> + PartialEq + Rem<Output=T> {
fn fizzbuzz(&self) -> FizzBuzzResult<&Self> {
let zero = T::from(0);
match (*self % T::from(3), *self % T::from(5)) {
(x, y) if x == zero && y == zero => FizzBuzzResult::FizzBuzz,
(x, _) if x == zero => FizzBuzzResult::Fizz,
(_, y) if y == zero => FizzBuzzResult::Buzz,
_ => FizzBuzzResult::Num(self),
}
}
}
これでu128でもf64でも動く ざんね〜ん
f64はStepを実装していないので(1.0)..=(100.0)できませ〜ん
いっけね! >>802
え?
>>794のas f64方式で動きましたけど impl XXX for T で where にだらだら制約書くやつは変に制約強くなりがちだから実装の共通化が目的ならマクロ使った方が良い
実装の共通化のために継承を使うようなもので、目的に対して不適切な手段を使っているように思う パラノイアみたいにジェネリックジェネリック言う割にはそこだけ{integer}なのは気にしないんだ
FizzBuzzなんて>>781でいいんだよ
もっと意味のある仕事をしようぜ ジェネリックにするのも時間の無駄だが
traitにするのがそもそもガイキチ
>>781は無限ビジーループで論外
最低限でも関数の入出力は考えろ マクロ使うしかないんだけど、マクロの部分はエディタのサポートがちょっと弱くなるのが残念だよね FizzBuzz を過剰にジェネリックにする意味はないが、
ここではジェネリック化の手法を色々知るというのがトピックで FizzBuzz はただの例だよ。 >>797
> トレイト境界となるパーツのトレイトは個別に型列挙してimplする必要がある
もしよかったら具体的にどういうことか教えてちょ
不勉強すぎてまったくついていけない
>>798
> 定数だけ impl すればメソッド自体は共通化できるかな
定数だけimplするとは?
>>800
(´・∀・`)ヘー
勉強になりました
Fromってそうやって使うんやね
>>804
みんながどうやらマクロで解決してるらしいのは流れみて分かったが
具体的にはさっぱり分からんのでツライところ
おまえらって詳しくてスゴイわ >>809
> 定数だけimplするとは?
実際には動作しないけどコードで言えばこんなのを考えてた。
https://ideone.com/vSnAET >>810
なるほど
言わんとする意味はバッチリ分かりました
みんな色々考えるんだなw >>810
RemのOutput型を指定すればちゃんとE0158エラーになるよ >>812
> マクロでtraitを実装する
(´・∀・`)ヘー
imple X for Yまるごとマクロの中に来るんやね
Rustのマクロについては調べたこと無かったけど
やっぱやりたいことはできるようになってそうで安心
ありがとうございました >>815
それいいな。
先にゼロと比較してから true にマッチさせる部分よりもゼロを作るテクニックのほうが面白いと思った。 >>801
i8で動かない原因はFromを使っているためなのでTryFromを使えばi8でも動く
use std::convert::TryFrom;
use std::ops::Rem;
use num::CheckedAdd;
fn fizzbuzz<T>() -> impl Iterator<Item=FizzBuzzResult<T>>
where T: Copy + PartialEq + CheckedAdd + Rem<Output=T> + TryFrom<usize>,
{
let [zero, one, three, five] = [0, 1, 3, 5]
.map(|n| T::try_from(n).ok().unwrap());
itertools::unfold(zero, move |n|
n.checked_add(&one).map(|new| {
*n = new;
match (new % three, new % five) {
(x, y) if x == zero && y == zero => FizzBuzzResult::FizzBuzz,
(x, _) if x == zero => FizzBuzzResult::Fizz,
(_, y) if y == zero => FizzBuzzResult::Buzz,
_ => FizzBuzzResult::Num(new),
}
})
)
}
fn main() {
for f in fizzbuzz::<i8>() {
println!("{f}");
}
}
ちゃんとi8の上限127で停止 >>818
すいません
マクロで>>817を実装可能なのですか? どっちがいいかどうかはともかくとして、817が使ったであろうnum-traitsのcrateのCheckedAddもマクロで実装されてるよん
こういうのはマクロになりがち どちらも正しい
・基本的な性質のTraitは型を列挙してimplする →マクロになる
・それら以外のTraitは基本Traitを組み合わせる →Trait境界の列挙となる >>822
ところで>>817のイテレータはマクロでできる? 現状はジェネリックじゃ実現できない事が多々あるから性能面を重視するならマクロになる
数値系は特に 型パズルオナニストきついなぁ
長いコードをレスに直接貼りたがる性癖どうにかならんの? 型パズルとか言ってるやつ
トレイト境界を理解できていないのか >>825
マクロとtraitで性能が変わりうるのってどういう時?
traitだと回りくどい記述になりがちということ? >>828
BigIntは参照で渡したいけどプリミティブ数値型は値で渡したい
traitだと値か参照かどっちかにしかできない、とかじゃねーの知らんけど >>827
トレイト境界を理解できないやつがいると思っちゃうところが相当ヤバいんですけど
さすオナ >>829
そういうときは Cow を使うもんじゃねーの
しらんけど マクロとトレイトじゃなく
マクロとジェネリックの比較 >>826
Rustに限った話じゃないけど、playground系で貼らないのは自己顕示欲の率直なあらわれだと思う 辿れなくなる (サービスが終わったり障害が起こる) 可能性もあるから短いものはなるべく直接貼るようにしてる。
大抵は収まる大きさにならないけど。
5ch 自体が見れない場合はしょうがないんだが、話題に付随するコードが見れないときはだいぶんイラッとするぞ。 >>836
すでに投稿されてるものを読む側の話なんだが……。 俺も貼れるなら直貼りするわ
いちいち見に行くのも面倒だろうし
そもそも自己顕示欲ないなら貼らないしw >>835
Githubより5chを信頼してるんだなwww
さすオナ >>839
話題が見れないときよりも話題は見れるのにコードが見れないほうがイラッとするという話なんやが。 ちゃんとコンパイルとrustfmt通したもの貼りたいからplayground使う
スマホからも確認できて便利だよ >>842
うん。 勝手にいらついてるよ。
でも俺は誰かをいらつかせないためになるべくレス内にコードを書くって話。 独りよがりじゃない直貼りは別にいいと思うよ
>>780や>>781くらいなら全く気にならない
>>785もまあ可
ってアウトなの一人だけじゃん 5chに貼られてインデントもないコードは読みづらいし、結局コピペして整形しなおすことになるんだから、最初からplaygroundとかを使って貼れよ
もちろんちゃんとコンパイルが通って実行可能な状態でな。
言及もせずにcrateやunstable機能使われてると、なかなか実行確認できずに面倒だからな
それが閲覧者のことを考えてる、ってもんだ
サービスダウンが心配なら、複数のサービスに貼り付けてくれればいいぞ、まあそこまではいらんけど たしかにインデントもないウンコな直貼りは約1名だけか ウェブブラウザだとインデント消えるのか
playground使った方がいいな >>847
妄想?
インデントが無いコードをこのスレで見たことないんだが 連続した半角スペースがちゃんとインデントとして表示されるのは一部の専ブラとか使ったときだけ
通常のウェブブラウザではHTMLとして処理されて消える >>850
ところが>>847は、一人だけインデントがない、との主張だからそのケースとは違う 主張だなんて大げさな
ウンコが約1名いる
そのウンコはインデントしない
そのウンコは直貼りする
それだけの話だろ スレの最初から見たけど全てのコードがインデントされてるな
1名だけインデントしていないとか言い出す人は何らかの精神病なんだろうけど 二度手間だから最初からPlaygroundに貼りませんか?って話なのに
ウンコが何人いるかなんてどうでもいい話ばかり気にするのね いちいち見に行くの面倒だからここでいいんじゃね
でも使いたい人を責めることはしないよ どこの世界でも同じだが
特定の意見や特定の方針を他人に押し付ける人やイラつく人は嫌われる ブラウザにでっち上げた言語を無駄に抱き合わせることは、押し付けじゃないの? ウンコード直貼りと自演擁護はいつもの複製おじさんだから
適当な所で切り上げないと時間の無駄だよ >>862
> 自演擁護
これまたでかいブーメランだな、久々に見たわ
で、インデントされてない1名ってどれ?w うんこ等の汚い単語を使うのはいつものキチガイだから無視するのがよいかと >>863
知らんがなw
直貼りでインデントされてるコードなんて見当たらない せめて技術的な話でやりあってくれめんすw
煽りオンリーは時間の無駄でつよ 貼られたソースコードはクリック一つで自分の環境やplayground等に移せるようにしている
逆にplayground等に貼られたソースコードは自動引用表示してる
どちらもほぼ同じ表示となるため両派とも自由に好みのスタイルで貼ってくれて構わない インデント付きで表示される5chブラウザが存在するの!? 最近はjaneでも連続半角スペースが表示されるようになってる
かなり短いコードじゃないと見にくいが >>870
ウンコ・オブ・ウンコを撮るあたりはさすがオナニスト おまえらrustfmt使ったことないのか?
クリックで1つで呼び出せるようにしてるので
インデントが崩れていようが元が変なインデントだろうが綺麗に見やすく表示できてるぞ
他者に文句を言う前に自分で技術で解決しろ 直貼りやインデントは置いといて
コードの中身の技術的な面で何がウンコなのかを書いてくれ おっしゃる通り
技術的な議論だけにしていただきたい
表示問題はrustfmt自動適用 自動適用するuserscriptなりextensionなり作ったの? めんどくせーから5chでシンタックスハイライトとrustfmtとコード実行できるようにしとけ 各自の環境に合わせて様々な対応方法があるな
Webブラウザならブラウザ拡張でもいいしブックマークレットでもよい
専ブラは多種あり各々で可不可が違うのでノーコメント
自作ブラウザなら当然楽勝
ところでrustfmtは標準入出力かファイルだが公開ウェブサービスある?
無ければhyperで作ってローカルに動かして使う その次善策としてplaygroundで貼るという手法があります 俺はウェブブラウザで見てるけど間にサーバを挟んでいるのでrustfmtもそこで呼び出すことにする
playgroundからのコード自動引用もやりたいが貼られたURLからrustコードを取ってくるにはどうすればいい?? 「独りよがりの長いコードを繰り返し直貼りするな」
「見る側がフォーマットすればいいだけ」
なんじゃこの流れ
フォーマッタは汚物浄化装置じゃないぞ プログラム板でコードが貼られて困る人はいないだろうけど
どうしても欲しい人はコード表示on/offボタンを付ければ良さげ
いずれにせよ各個人の好みの問題は各個人で解決すべき オナニーうんコードが問題であって直貼りが問題じゃないんですよ 技術面に触れないと突っ込まれそうなので、>>817についての個人的な感想ですが
Tのトレイト境界に関して、数が多くなるのは仕方の無いケースもあるが、この例では単に数が多いだけでなく、
CheckedAdd等の内部実装に踏み込んだトレイトまで指定されていて、その点が良くないと思います
例えばCheckedAddを実装していなくてもFizzBuzzできる型に対して、同じ関数を使うことができない
またCheckedAddを実装しているがより効率の良いアルゴリズムで実装できる型の場合でも、この関数では効率の悪いアルゴリズムで処理するしかない
ので>>822のようにFizzBuzzできるかどうかをtraitとして持たせ、実装詳細は各型に任せるのがよいと思います
こんなことで長文書くのも馬鹿馬鹿しいね >>884
その主張は全て間違い
checked addしなければオーバーフローしてプログラムが破綻するだけ
そしてchecked addはCPUレベルではオーバーフローフラグを見てるだけなのでコストゼロ
さらにCheckedAdd traitは任意の型に実装可能 >>885
破綻しないよww
CheckedAddに依存する必要性全くないじゃん >>884
そのFizzBuzzイテレータ>>817を
checked_add()使わずに効率的にプログラミングするのは不可能だと思います >>885
Wrapping<T>を使って無限に返すイテレータを返して利用者側でtakeさせる設計でもいいよね >>887
checked_addを使うか否かではなく
T: CheckedAddという強い制約の必要性について聞かれてるんだと思うよ Rustにおいてchecked_add (及び同等で返し方が異なるだけのoverflowing_add) は数値を扱う上でオーバーフローを起こさせないための必須の存在
そしてchecked_addは整数型ならばadd直後のCPUのoverflowフラグを見るだけだからオーバーフローを検出するために最もコストが低く済む存在
だからその手のものを素直にコーディングすれば必ず登場
そのtrait CheckedAddを使うのは違和感なく自然に思えるが他にどんな手段があると主張している?? 「ゼロからその型の最大値まで一個づつたどるイテレータ」
なんてもんに固執してるあたりがまずさいしょに珍妙
順序や範囲は他の理由で決定させて十分だと思う人は
イテレータとfizzbuzzをきれいに分離して考えてる >>891
その件は最初にFizzBuzzの話が出てきたときに終わっていて単なる例にすぎない
話が分かりにくいならばもっと単純な例としてフィボナッチ数列イテレータでどうかな
ご存知だと思うけど足し算するだけの数列ね そうか>>817が急に脈絡なくイテレータの話にし始めたのか
>>891に完全同意
適当なイテレータ持ってきて.map(fizzbuzz)でいいね
そっちはRem+PartialEqと、0と3と5を持ってくるための制約で済む、それなら自然だと思う >>894
経験の違いじゃない?
関心事の分離を意識できないのは使い捨て感覚ででしかコードを書いたことのないからだと思う
組織で開発してたり長く維持する製品コードを書いた経験があればトイプログラムでも関数の責務くらいは意識して書くから フィボナッチ数列イテレータでも同じだろう
fn fibonacci<T>() -> impl Iterator<Item=T>
where T: Clone + TryFrom<usize> + num::CheckedAdd,
{
let [zero, one] = [0, 1].map(|n| T::try_from(n).ok().unwrap());
itertools::unfold((zero, one), |(m, n)|
m.checked_add(&*n).map(|f| {
*m = n.clone();
*n = f.clone();
f
})
)
}
pub fn main() {
for f in fibonacci::<i8>() {
print!("{f} ");
}
println!();
} フィボナッチとFizzBuzzを同一視する時点でw FizzBuzzの判定処理には Checked は不要
Overflowしないような列挙をするイテレータを実装する Checked が必要
という話だが、 >>817 でこういうイテレータの機能が突然持ち込まれたせいで、みんなが混乱したんやぞ >Overflowしないような列挙をするイテレータを実装する Checked が必要
「なら」が抜けてた
Overflowしないような列挙をするイテレータを実装するなら Checked が必要 一方で>>884氏や>>886氏はFizzBuzzイテレータにまでCheckedAddが不要と主張している
もちろんこの主張は間違い FizzBuzzイテレータw
さすが複製おじさんww >>884 >>896
その分離方式でも同じ結果となる
上限チェックのところでchecked_addが必要 >>903
確かに強弁の感じが所有権の複製と人と同じっぽいな
もしそうなら議論は難しそう プリミティブの整数型なら>>824みたいに0..=<T>::MAXでもいいし、
ジェネリックにやりたいなら0..=<T as num::Bounded>::max_value()もある
つーか自分が唯一の正解みたいなこと平気で言うそういうとこやぞ 範囲とか順序とかはまた別の関心事だもんな
元々はせいぜい整数のfizzbuzz表現であって
>>906
そうそう
そういう感じよね >>906
それは失敗パターンかな
<T>::MAXはTが自作の型の時に定義できない イテレータを返したいならイテレータアダプタとして実装すればいいだけ
FizzBuzzはイテレータのソースにすべきものじゃない >>906
checked_addの代わりにMAXやmax_valueを使うのは良くないです
checked_addは足し算の時に自動的に発生するオーバーフローを利用するため比較演算が発生しませんが
MAXやmax_valueはその値と比較する演算が余分に発生します
checked_addを使いましょう >>896
何か腑に落ちたわ
多少なりともチーム開発の経験があれば
独りよがりなコードをドヤ顔でペタペタ貼り付けたりしないもんな 簡単に差分やマージできる環境と5chスレを比べても無意味じゃないか チーム開発をやっててもオレオレエンジニアっているからね
マウンティング・強弁・逆ギレはメンタリティの問題でもある
「オレが書いたコード、すごいだろ!」
https://xtech.nikkei.com/atcl/nxt/column/18/00205/032300028/ >>911
何を言っとるんじゃい
外から渡せばいいじゃんって話をしてるのわかってる?
fizzbuzzは100からのカウントダウンでやったって別にいいんだぞ
traitやenum使う前に関数の入出力考えなよ 普通に考えたらこんなイテレータはstd::ops::Rangeとかで十分だし、しかもより高機能だから、自分で実装しなくていいよな
イテレータの勉強をしてるならともかくとして >>906
その<T as num::Bounded>::max_value()も一つの手であるが意外に致命的な欠陥がある
例えばBigIntなどの最大値がない型に対してBounded traitを実装できない
そして実際にBigIntではimplされていないため使えない
一方で<T as num::CheckedAdd>::checked_add()も同種の問題が起きないのか、だが
例えば最大値が存在しないBigIntでもCheckedAddはimplされている
オーバーフローが発生しないためNoneを返す必要がなく常にSomeを返す形となっている
つまり自分で作った型の場合であってもCheckedAddならば柔軟に対応できる
したがってRustで無限となりうる数列を扱う時はCheckedAddを使用することが好ましい impl FizzBuzz for T
vs
impl FizzBuzz for u8, u16, ...
の話だと思ってたんだが話が発散しすぎ >>915
>>918
FizzBuzzは単なる話の出発点の例の一つに過ぎなくて既に皆はもっと一般的な話をしているようにみえる
皆もFizzBuzz限定の話なんかに興味はなくて一般的な話に興味があるからではないかな >>917
0からの列挙を型だけから導出できないといけない理由は何なのさ >>920
各型には上限値(とその有無)がありメモリサイズとトレードオフだからそこは気を使うよ
Rustではrelease modeだとC/C++と全く同じでオーバーフローしてもpanicは発生せずに数値がラップしうる
例えばi32で2147483647に1を足すと普通の足し算の+つまりadd()だと結果は-2147483648となる
これは数値計算だけでなく単なるカウンター利用に至るまで深刻な結果を招きうる
そのため足し算ならばchecked_add()等を必要に応じて使い分けることになる >>919
impl Foo for T where クソ長制約
vs
impl Foo for 具体的な型
という話なら多少興味もってもらえるだろうか
impl Foo for T は基本的に避けるべきだと思う >>922
Rust標準ライブラリでも他のクレートでもimpl Xxx for Tは山のようにある
それを避けるべきとの主張は全く意味不明 >>918
> impl FizzBuzz for u8, u16, ...
これもう構文として取り込んだらいいのにな
impl_fizzbuzz(u8, u16, ...)
こういうのを書く文化をいっそ言語の構文に格上げして >>923
impl Foo for T where 制約多数って例えばどのtraitの実装? >>924
そういう型別impl列挙は主に基本的なTraitにおいて行われており
それらを組み合わせてTrait境界とする上位のTraitでは列挙せずfor Tで済むようにRustは上手く設計されている >>800では対応できていたはずのf64が>>817でCheckedAdd追加したせいで対応できなくなってるよとか指摘すればいいの? >>926
上位のtraitって例えばどういうもの?
それは本当にtraitにすべきものなの?
traitにすることでどういうメリットがあるの? おまえらの議論が唐突すぎてよくわからない
今日の議論の発端となった今朝の書き込み>>884と元コード>>817及びそれ以降のレスには
impl … for Tなんて話は全く出てきていないぞ
ちなみにコードは以下のようになっている
> fn fizzbuzz<T>() -> impl Iterator<Item=FizzBuzzResult<T>>
> where T: Copy + PartialEq + CheckedAdd + Rem<Output=T> + TryFrom<usize>,
> { たぶんだけど>>922 >>924の話は
そのfn fizzbuzz<T>() where T: Boo + Foo + Wooとトレイト境界ジェネリックにしているのを禁止して
各々fn fizzbuzz_i8()、、、fn fizzbuzz_u128()を用意すべきという主張なんじゃないか >>929
>>800,804の話題を掘り起こしてしまった >>930
言葉足らずでスマソ>>924で言いたかったことは
macro_rules! impl_foo {略} // 中でimpl Foo for
impl_foo!(u8, u16, ...);
今はマクロ使って↑こうなりがちなものを
いつか言語として↓こうなったらなぁという話
impl Foo for u8, u16, ... {略}
お分かりのとおり非常にしょうもない些細な話w >>931
その>>800のコードは特に問題が無いのではないか
強いて言えばその後に出たいくつかの改善案を反映して
impl<T> FizzBuzz for T
where T: Clone + PartialEq + TryFrom<usize> + Rem<Output=T>
{
fn fizzbuzz(&self) -> FizzBuzzResult<&Self> {
let [zero, three, five] = [0, 3, 5]
.map(|n| T::try_from(n).ok().unwrap());
match (self.clone() % three == zero.clone(), self.clone() % five == zero) {
(true, true) => FizzBuzzResult::FizzBuzz,
(true, _) => FizzBuzzResult::Fizz,
(_, true) => FizzBuzzResult::Buzz,
_ => FizzBuzzResult::Num(self),
}
}
}
こんな感じ? >>919
だからこそ>>817がウンコードだと言われてるのに
わかんないかなぁ >>922
これはそうだな
impl Foo for Tはstdに入れるくらいのよっぽど汎用的なものでもなければ避けるべき >>933
それtraitにする意味ある?
>>935
FooExt もありだと思うが where T: Foo と制約はシンプルであるべき >>936
確かにextension traitは有りだな impl<T> _ for T where T: ... 形式のことを blanket implementation って言うんですね
cargo doc で型のページの下の方に出てくるのは知ってたけど、正確な定義は今知った >>936
元々の質問がi32など各整数にメソッドを増やしたいとの質問だったようだ
それで>>789からずっと
trait FizzBuzz {
fn fizzbuzz(&self) -> FizzBuzzResult<&Self>;
}
となっていてそれを前提に皆が話をしてる
ちなみにコードがスレへ貼られていないと検索しても出て来ずに不便だとわかったw >>939
>>804-806辺りで皆から指摘されてますやん >>940
そいつらは例えばイテレータメソッドを増やしたことすらない初心者かもな
Rustでメソッドを増やすにはトレイト定義が必須で欠かせない そもそもメソッド増やす必要ありましたか?
仮に方法だけ質問されたとしても、「やめとけ」と答えるのも回答のひとつですよ な、複オジ相手にしても時間の無駄だっただろ?
いい加減学習しようぜ >>942
メソッドを増やすべき状況は多々あります
既に出ているイテレータメソッド等もその一例です
そして今回のFizzBuzzはあくまでも例ということですからFizzBuzz自体をメソッドにするべきか否かの議論はどうでもよく無意味でしょう
メソッド化を実現できること自体の方が本質にみえます >>942
最初の質問者 (>>781) はまだ Rust の基礎を学んでいる途中なのだというのが前提にある。
FizzBuzz についての質問であったとしても別に FizzBuzz を書きたいわけではなかろう。
Rust を学ぶ題材として試しに FizzBuzz を取り上げてるだけだ。
だから「FizzBuzz では」やめとけというだけでは回答として不十分。
「『必要であれば』書き方はこんな感じだよ」という形で話を膨らませるのはごく普通の対応に思える。
Rust 自体に習熟してないのにその上での設計の良し悪しなんてこの段階で論じるようなことでもない。 >>942の人は単なる反抗期なんじゃね
書き込みを見ると何でも反対してる
それでいてCheckedAddを使わずにMAXを使え!など提案が的外れ >>943
すみませんでした
しばらくROMります >>941,944,946
これが複オジ論法
技術的な議論は無理 >>933
zeroのclone()は不要
他はOK
それならBigIntでも動作する 避けるべきというアンチパターンが出来ている時点で欠陥言語、 where T: Fooなどと書けるがRustは決してシンプルじゃない Rustの目標はシステムプログラミング言語だから、C/C++に比べてマシならおーけー >>951
避けるべきと言ってる人の独りよがり
根拠も示さず個人的に毛嫌いしてるだけ ,―彡 ⌒ ミ―、
〈 〈| ´ん` |〉 〉
\ ヽ _ / /
/ /みんなで
/ /ホモセックス 反対!君とうんこ!君は代案コードを出さない(出せない)から無視しとけ >>948
あーなんか既視感あるとおもったら菅話法だw >>933
Rustはそうやってシンプルに安全に多型に対応できるところがいいよな >>945
なるほどこれがオナニー指向の思考回路か C言語でプログラミング入門した口だけどRustみたいな関数型言語わからなくて困ってる
例えばOCamlみたいな型推論前提で書かれているコードはどの変数がなんの型になるのかわからなくてつらい思いしている
関数型言語のプログラマはみんな自分で型を推論しながらプログラミングしてるんですか? >>959
むしろ型推論してくれるからプログラマーは楽
ただしどこかで歯止めがある方が安全安心確実だからRustでは関数の入出力のみ明示する
それも例えば>>929の返り値のように型そのものではなく抽象的にトレイト名で記述も可能
もしある値(式)の型を知りたかったらプログラムで表示も可能だけど一番簡単なのは
let a: i32 = 値;
とデタラメな型名i32を宣言してやるとコンパイラがエラーとして正しい型名を教えてくれる 基本的にはIDEに型を教えてもらってたけど、慣れてくると自分でどんどん型がわかるようになる >>959
VSCode+rust-analyzerなら変数の型やメソッドチェーンの途中の型が全部出るよ >>959
どの型に確定するのか把握しなければ使えないのだとしたら、その関数の設計が悪い。
まあ程度問題ではあるけど……。 >>960,962,963
ほーんなるほど
今ocaml勉強しているんだけど
if式のthen節とelse節の式の型は両方一致するとか、
match式においてもすべての分岐の式の型は一致するといかいったことを把握していってるわ
それ取っ掛かりにして関数全体の型把握するようにしたい
あと分岐の片方でラムダ抽象置いて束縛変数導入したらばもう一方の分岐ではconst関数に第一引数適用したの置いて分岐全体の型を合わせるとかいうテクニックとかも他人のソースから学んだンゴ
でも他の言語に比べてocamlのソースはなかなか転がっていない印象を受けるんごねえ
あとSKIコンビネータとかの型も式から推測するのもややこしくて難しいンゴねえ rust-analyzerっていえばさ
俺のVSCodeをYoutuberのと見比べると、構文間違えなどのアンダーラインが出現・消滅するタイミングが違うんだよね
Youtuberらのがリアルタイムで線が引かれているのに対して、俺のは保存しないと線が引かれたり消えたりしない・・・・しかも、俺の手元ではMacでもWindowsでも一緒の症状・・・・
誰かエスパーさんいたら解決策を教えて!!! >>965
自動セーブにする必要があるとかじゃないの? >>967
審査無しでユーザーが好きに登録できるパッケージマネージャにはよくありがちなことだな
パスワードが盗まれて正当なパッケージが置き換えられたわけじゃないからまだまし
Firefoxの拡張の中には第三者が権利を正当な形で引き継いだその後の更新でマルウェア化しているものがあるって報告があるくらいだし Rustで書くと依存crateが100オーバーになるのも珍しくないから
アプリ開発者がリリース単位で常時全部チェックするのは手間がかかりすぎる
全チェックじゃなければcargo crevとかで閾値決めとくとかしかないよね >>972
マルウェアというよりアクセス履歴を収集するようになったってやつでしょ >>824
ホントだ
127の次でpanicした
(1_i8..).for_each(|n| print!("{n} "));
release modeではpanicではなく127の次が-128になって永久循環 適当に作れば溢れる前に止まる
fn countup<T>(start: T) -> impl Iterator<Item=T>
where T: Clone + TryFrom<usize> + num::CheckedAdd,
{
let one = T::try_from(1).ok().unwrap();
itertools::unfold((start, true), move |(n, is_first)| {
if *is_first {
*is_first = false;
Some(n.clone())
} else {
n.checked_add(&one)
.map(|new| {
*n = new.clone();
new
})
}
})
}
fn main() {
countup(1_i8).for_each(|n| print!("{n} "));
} >>975
1_i8..=i8::MAXにすればいいだけ
型のMAX値までRangeFromでイテレートするなんて処理は現実のプログラムでは必要ないから >>977
それは数値型にしか使えないので>>976かな >>976は悪いお手本が盛り沢山
真似しちゃダメだぞ Rangeをpanicしないように扱う方法ないの?
CheckedRangeみたいなやつとか >>980
Rangeはオーバーフローしないよね?
RangeFromでオーバーフローして困るなら上限を指定しないと
スレ立てもヨロ >>982
もっと厳しそうなStringで>>976をやってみた
Zの個数で数を表すZ
#[derive(Debug,Clone)]
struct Z(String);
impl std::fmt::Display for Z {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<usize> for Z {
fn from(n: usize) -> Self {
Z("Z".repeat(n))
}
}
impl std::ops::Add for Z {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Z(self.0.clone() + &(rhs.0))
}
}
impl num::CheckedAdd for Z {
fn checked_add(&self, rhs: &Self) -> Option<Self> {
Some(Z(self.0.clone() + &(rhs.0)))
}
}
fn main() {
countup(Z::from(1)).for_each(|n| println!("{n}"));
}
ちゃんと動作してZの数が増えて行くんだな >>984
それは独自の型であってStringではないよ
上限までイテレートするのに上限が無い型を実装して何がしたいのかわからないが
countup(Z::from(usize::MAX))とかで確認した? >>985
Rustのorphan ruleを知らないのかよ
独自の型に対してしか既存traitを実装できない規則なのでそこは独自の型で正しい >>986
全くもって間違ってるよ
アプローチが間違ってるから>>976や>>984みたいなものしかできない >>984
“Z”を繰り返したいだけなら
(1..100).map(|n| “Z”.repeat(n))でいいのに
新しい型を作って4つも5つもトレイト実装することに何かメリットあるの? >>988
抽象的な考えが出来ない人なのかな
そういうのはあくまでも例であってZを表示したいわけではないことくらい分かるでしょ >>976
上限のある型を作ってトレイト境界を満たしてやるとちゃんと上限で止まるんだな
#[derive(Debug,Clone)]
struct FiveBits(usize);
impl FiveBits {
fn make(n: usize) -> Option<FiveBits> {
(n >> 5 == 0).then(|| FiveBits(n))
}
}
impl TryFrom<usize> for FiveBits {
type Error = &'static str;
fn try_from(n: usize) -> Result<Self, Self::Error> {
FiveBits::make(n).ok_or("overflow")
}
}
impl std::ops::Add for FiveBits {
type Output = Self;
fn add(self, rhs: Self) -> Self {
FiveBits::make(self.0 + rhs.0).unwrap()
}
}
impl num::CheckedAdd for FiveBits {
fn checked_add(&self, rhs: &Self) -> Option<Self> {
FiveBits::make(self.0 + rhs.0)
}
}
impl std::fmt::Display for FiveBits {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.0)
}
} >>980
Rangeは上限ありだから大丈夫
RangeFromならば>>976みたいなのでいいんじゃない? >>985
それは君が思い込みで勘違いをしている
>>976のイテレータを見るとchecked_addが使われているため
その型に上限が有れば上限で止まるから君の言うとおり
しかしその型に上限が無ければ(リソースの有る限り)無限に進むことになる >>789
> fn fizzbuzz(&self) -> FizzBuzzResult<&Self> {
その関数を使わせてもらってイテレータにしようと思ったら
参照を返しているために非Copy型に対して上手くいかなくて手詰まってしまった このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 90日 14時間 44分 13秒 5ちゃんねるの運営はプレミアム会員の皆さまに支えられています。
運営にご協力お願いいたします。
───────────────────
《プレミアム会員の主な特典》
★ 5ちゃんねる専用ブラウザからの広告除去
★ 5ちゃんねるの過去ログを取得
★ 書き込み規制の緩和
───────────────────
会員登録には個人情報は一切必要ありません。
月300円から匿名でご購入いただけます。
▼ プレミアム会員登録はこちら ▼
https://premium.5ch.net/
▼ 浪人ログインはこちら ▼
https://login.5ch.net/login.php レス数が1000を超えています。これ以上書き込みはできません。