公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust
公式ドキュメント
https://www.rust-lang.org/learn
Web上の実行環境
https://play.rust-lang.org
※Rustを学びたい人はまず最初に公式のThe Bookを読むこと
https://doc.rust-lang.org/book/
※Rustを学ぶ際に犯しがちな12の過ち
https://dystroy.org/blog/how-not-to-learn-rust
※Rustのasyncについて知りたければ「async-book」は必読
https://rust-lang.github.io/async-book/
※次スレは原則>>980が立てること
前スレ
Rust part23
https://mevius.5ch.net/test/read.cgi/tech/1708677472/
探検
Rust part24
■ このスレッドは過去ログ倉庫に格納されています
2024/05/27(月) 06:41:26.82ID:T4AFD1f4
462デフォルトの名無しさん
2024/06/29(土) 14:06:46.53ID:H9n2Ca7a リファクタリングの原則のひとつとして外側から見たときに変わらないというのがある。
内と外を分ける境界線がどこなのかというのは場合によるので UI レベルで同じなら良しとすることもあるけど、普通は適当なモジュール単位でやるだろう。
「変わらない」ことの保証のひとつとして型やライフタイムアノテーションは頼りになるよ。
型システムがあてにならないほどの大改革ならどうせ全部書き直しなので足を引っ張られることもない。
内と外を分ける境界線がどこなのかというのは場合によるので UI レベルで同じなら良しとすることもあるけど、普通は適当なモジュール単位でやるだろう。
「変わらない」ことの保証のひとつとして型やライフタイムアノテーションは頼りになるよ。
型システムがあてにならないほどの大改革ならどうせ全部書き直しなので足を引っ張られることもない。
463デフォルトの名無しさん
2024/06/29(土) 14:24:33.15ID:lbQtaoAJ Rustはリファクタリングには全く向いていない
464デフォルトの名無しさん
2024/06/29(土) 14:31:05.74ID:dyJ1RvLM いつも汚いコードを貼り付けてた複オジがリファクタリングは簡単などと言い張ったところで全く説得力がない
465デフォルトの名無しさん
2024/06/29(土) 14:38:55.22ID:pz5Aaald 数のイテレータで遊んで満足してる人に機械学習の文脈が理解できるわけないやん?
466デフォルトの名無しさん
2024/06/29(土) 14:41:30.81ID:Kxp5xIIU 掲示板に貼れる程度の内容なら
リファクタリングしても知れてるでしょ
リファクタリングしても知れてるでしょ
467デフォルトの名無しさん
2024/06/29(土) 15:08:40.24ID:BT1eNZRh >>463
Rustはリファクタリングに向いている言語だよ
リファクタリングで最も重要なことはその前後で同じ機能動作が保証されることだけど
そこで静的型付け言語が有利なことは当たり前としてRustのアクセス競合排他原則がさらに大きく効いてるよ
データ書き換え中の読み取りによるバクがリファクタリングによって入り込むことも防いでくれているね
Rustはリファクタリングに向いている言語だよ
リファクタリングで最も重要なことはその前後で同じ機能動作が保証されることだけど
そこで静的型付け言語が有利なことは当たり前としてRustのアクセス競合排他原則がさらに大きく効いてるよ
データ書き換え中の読み取りによるバクがリファクタリングによって入り込むことも防いでくれているね
468デフォルトの名無しさん
2024/06/29(土) 15:23:13.20ID:PsPEDCdZ デジタル小作人やめるレベルの大手術ではなく
地主との関係が変わらないことを保証したいんだな
地主との関係が変わらないことを保証したいんだな
469デフォルトの名無しさん
2024/06/29(土) 15:34:20.66ID:KH8yb7Br それまで参照を持たなかった構造体にメンバとして参照を持たせると、型にジェネリックライフタイムが付いて、その型の使用箇所全部でライフタイムを書く必要がある
さらに悪いことに、実際のところこれは必要ではなく、ライフタイムを書かなくても省略されていると見なされてコンパイルが通ることもある
しかしこれでは意図通りのライフタイムになっていないことが多く、その型の使用箇所を増やしたときに初めてそのことに気づくことになる
Rust特有のリファクタリングしづらさは、あるよ
さらに悪いことに、実際のところこれは必要ではなく、ライフタイムを書かなくても省略されていると見なされてコンパイルが通ることもある
しかしこれでは意図通りのライフタイムになっていないことが多く、その型の使用箇所を増やしたときに初めてそのことに気づくことになる
Rust特有のリファクタリングしづらさは、あるよ
470デフォルトの名無しさん
2024/06/29(土) 15:52:41.67ID:jlQztVvs ライフタイム関連に限らずRustのリファクタリングは
他言語に比べて波及する範囲が大きくなりやすいんだよね
それで作業量が多いからしんどい
しんどさと難しさは必ずしもイコールではないんだけど
サクサク変更できる言語を経験してると
Rustのリファクタリング時には精神的なエネルギーが相当必要
他言語に比べて波及する範囲が大きくなりやすいんだよね
それで作業量が多いからしんどい
しんどさと難しさは必ずしもイコールではないんだけど
サクサク変更できる言語を経験してると
Rustのリファクタリング時には精神的なエネルギーが相当必要
471デフォルトの名無しさん
2024/06/29(土) 16:01:57.62ID:obFhbebh >>469
リファクタリングの作業の大きさに対して、必要なライフタイム注釈を付けるだけの些細なことが障害になったことはないな。
ライフタイム注釈が'aになるか'_になるか省略できるかは、その必要性と省略ルールに基づくだけなので、そこで問題が発生することはないだろう。
リファクタリングの作業の大きさに対して、必要なライフタイム注釈を付けるだけの些細なことが障害になったことはないな。
ライフタイム注釈が'aになるか'_になるか省略できるかは、その必要性と省略ルールに基づくだけなので、そこで問題が発生することはないだろう。
472デフォルトの名無しさん
2024/06/29(土) 16:03:28.89ID:obFhbebh >>470
Rustでは様々なことをコンパイラチェックに任せられるため、リファクタリングで最も崩れにくく、人間の負担は他より小さい。
Rustでは様々なことをコンパイラチェックに任せられるため、リファクタリングで最も崩れにくく、人間の負担は他より小さい。
473デフォルトの名無しさん
2024/06/29(土) 16:10:10.85ID:FxtNCeeF 糠に釘
暖簾に腕押し
複オジにRust
暖簾に腕押し
複オジにRust
474デフォルトの名無しさん
2024/06/29(土) 16:52:22.95ID:KH8yb7Br >>471
「ライフタイム注釈が'aになるか'_になるか省略できるか」は、すべての使用箇所ごとに以下を検討したうえで決まる
* 追加するライフタイムは既存のライフタイムと同じであるべきか
* 既存と同じであるべきでないなら、そのライフタイムはどこで宣言すべきか(impl? fn? トレイトや構造体?)
それで1つの型がリファクタリングできたところで、
* トレイトや構造体にジェネリックライフタイムパラメータを追加した場合、そいつにも同じ作業がいる。最初から繰り返し
ここまでのすべての作業に尋常でない集中力が必要になる
繰り返しの中でライフタイムの宣言箇所の選択が誤っていたことに後で気づいたりすると悲惨だ
「エラーのあるコードをgit commitしない方が良い」という思い込みを捨て、選択を必要とするタイミングでgitに記録するようにして、
作業効率は安定はするようになったが、それでも作業を捨てるというのは気が滅入る
「あ、この関数の引数にライフタイム追加することになるけど、後で戻り値にもライフタイム追加することになるな」なんて思っても一挙に作業してはいけない
少なくとも自分の頭では作業の段取りを崩すだけだった
そしてここまでを全集中して完了してコンパイルを通すところまで持って行けても、クレート外の使用箇所でおかしなことにならないことは保証できない
ボローチェッカーは書かれている使用法が妥当であるかどうかしか検証しないからだ
こっちは体験談として言っているんだから、机上の空論を弄するのはもうやめなさい
「ライフタイム注釈が'aになるか'_になるか省略できるか」は、すべての使用箇所ごとに以下を検討したうえで決まる
* 追加するライフタイムは既存のライフタイムと同じであるべきか
* 既存と同じであるべきでないなら、そのライフタイムはどこで宣言すべきか(impl? fn? トレイトや構造体?)
それで1つの型がリファクタリングできたところで、
* トレイトや構造体にジェネリックライフタイムパラメータを追加した場合、そいつにも同じ作業がいる。最初から繰り返し
ここまでのすべての作業に尋常でない集中力が必要になる
繰り返しの中でライフタイムの宣言箇所の選択が誤っていたことに後で気づいたりすると悲惨だ
「エラーのあるコードをgit commitしない方が良い」という思い込みを捨て、選択を必要とするタイミングでgitに記録するようにして、
作業効率は安定はするようになったが、それでも作業を捨てるというのは気が滅入る
「あ、この関数の引数にライフタイム追加することになるけど、後で戻り値にもライフタイム追加することになるな」なんて思っても一挙に作業してはいけない
少なくとも自分の頭では作業の段取りを崩すだけだった
そしてここまでを全集中して完了してコンパイルを通すところまで持って行けても、クレート外の使用箇所でおかしなことにならないことは保証できない
ボローチェッカーは書かれている使用法が妥当であるかどうかしか検証しないからだ
こっちは体験談として言っているんだから、机上の空論を弄するのはもうやめなさい
475デフォルトの名無しさん
2024/06/29(土) 16:58:20.78ID:KH8yb7Br Rustはライフタイムさえ正しく書けていれば本当に有用な助けを与えてくれる
しかしライフタイムを正しく書くための助けはほとんど与えてくれないので、自分で書く必要があるときには上と同じような期待をしてはいけない
しかしライフタイムを正しく書くための助けはほとんど与えてくれないので、自分で書く必要があるときには上と同じような期待をしてはいけない
476デフォルトの名無しさん
2024/06/29(土) 16:59:51.95ID:TiydCxUm 知ったかぶりして間違ったこと書く
やんわり間違いを指摘される
反省せずに開き直る!
またこの流れ
ググればすぐわかるような間違いなのになんなんだろうな
やんわり間違いを指摘される
反省せずに開き直る!
またこの流れ
ググればすぐわかるような間違いなのになんなんだろうな
477デフォルトの名無しさん
2024/06/29(土) 17:06:14.07ID:HTwQ17U9478デフォルトの名無しさん
2024/06/29(土) 17:17:23.37ID:KH8yb7Br >>477
いいからこれでも読んでろ
https://github.com/pretzelhammer/rust-blog/blob/master/posts/translations/jp/common-rust-lifetime-misconceptions.md
> Rustのトレイトオブジェクトへのライフタイム省略ルールはどんな状況でも正しいというわけではない
> Rustはプログラムの意味についてプログラマよりも知っているわけではない
> Rustのコンパイラが吐くエラーメッセージでおすすめされる修正はコンパイルが通るようにするが、コンパイルが通り、 かつ プログラムへの要求をちゃんと満たしたものするわけではない
いいからこれでも読んでろ
https://github.com/pretzelhammer/rust-blog/blob/master/posts/translations/jp/common-rust-lifetime-misconceptions.md
> Rustのトレイトオブジェクトへのライフタイム省略ルールはどんな状況でも正しいというわけではない
> Rustはプログラムの意味についてプログラマよりも知っているわけではない
> Rustのコンパイラが吐くエラーメッセージでおすすめされる修正はコンパイルが通るようにするが、コンパイルが通り、 かつ プログラムへの要求をちゃんと満たしたものするわけではない
479デフォルトの名無しさん
2024/06/29(土) 17:26:08.00ID:3fxfEuZj それは省略ルールの結果が望むものと一致するかどうかは限らないという意味だぜ
間違っていると部分的にはコンパイルが通ったとしてもプログラム全体ではコンパイルエラーとなる
そのミスをコンパイラが見逃すことはない
間違っていると部分的にはコンパイルが通ったとしてもプログラム全体ではコンパイルエラーとなる
そのミスをコンパイラが見逃すことはない
480デフォルトの名無しさん
2024/06/29(土) 18:07:09.50ID:PsPEDCdZ 言語を比較しなくても
&Tに比べてRc<T>はリファクタリングしやすいとかいう認識でいいよな
ただ進化論じゃないんだから&Tが淘汰されてRc<T>が生き残るということはない
言語を比較すれば淘汰される言語もありうる
&Tに比べてRc<T>はリファクタリングしやすいとかいう認識でいいよな
ただ進化論じゃないんだから&Tが淘汰されてRc<T>が生き残るということはない
言語を比較すれば淘汰される言語もありうる
481デフォルトの名無しさん
2024/06/29(土) 18:13:00.59ID:E9RFAyQx >>469
その逆のリファクタリングを影響範囲が大き過ぎて無理って話をcargoのissueで見たことある
cargoはそれ以外でも技術的負債が溜まってるけど影響範囲が大きくなるから簡単に手を入れられないってことを中の人がよくボヤいてるね
その逆のリファクタリングを影響範囲が大き過ぎて無理って話をcargoのissueで見たことある
cargoはそれ以外でも技術的負債が溜まってるけど影響範囲が大きくなるから簡単に手を入れられないってことを中の人がよくボヤいてるね
482デフォルトの名無しさん
2024/06/29(土) 18:24:11.81ID:bsok8bJg C/C++をメモリ安全にするプロジェクト
https://www.itmedia.co.jp/enterprise/articles/2406/28/news084.html
Rustイラネになりそう
https://www.itmedia.co.jp/enterprise/articles/2406/28/news084.html
Rustイラネになりそう
483デフォルトの名無しさん
2024/06/29(土) 18:44:47.93ID:4ikwzvl0484デフォルトの名無しさん
2024/06/29(土) 20:21:20.41ID:U1RWDnMp >>480
Rc<T>の比較対象はTやBox<T>
・Tの参照は&T
・Box<T>の参照は&T
・Rc<T>の参照は&T
どれも同じになり&Tは不要とならない
違いはスコープから外れたとき
裸のTはTがスタック上ですぐ消える
Box<T>はTがヒープ上ですぐ消える
Rc<T>はTがヒープ上でカウンタが最後のときだけ消える
Rc<T>の比較対象はTやBox<T>
・Tの参照は&T
・Box<T>の参照は&T
・Rc<T>の参照は&T
どれも同じになり&Tは不要とならない
違いはスコープから外れたとき
裸のTはTがスタック上ですぐ消える
Box<T>はTがヒープ上ですぐ消える
Rc<T>はTがヒープ上でカウンタが最後のときだけ消える
485デフォルトの名無しさん
2024/06/29(土) 20:23:11.41ID:KH8yb7Br >>469
これか……
https://github.com/rust-lang/cargo/issues/7342
> I think the answer here is "Alex thought it was fun to avoid RefCell and Mutex", there's no real technical motivation.
「cloneを避ける/ロックを避ける/参照カウンタのコストを避ける」みたいなゼロコスト主義も節度を持ってやれってことね
とりあえず「型のジェネリックライフタイム引数を変更するのは多大なコストがかかる」という理解は合っていると思っておくことにするか
これか……
https://github.com/rust-lang/cargo/issues/7342
> I think the answer here is "Alex thought it was fun to avoid RefCell and Mutex", there's no real technical motivation.
「cloneを避ける/ロックを避ける/参照カウンタのコストを避ける」みたいなゼロコスト主義も節度を持ってやれってことね
とりあえず「型のジェネリックライフタイム引数を変更するのは多大なコストがかかる」という理解は合っていると思っておくことにするか
486デフォルトの名無しさん
2024/06/29(土) 20:23:40.20ID:KH8yb7Br >>481だった
487デフォルトの名無しさん
2024/06/29(土) 21:57:07.55ID:PsPEDCdZ 問題は節度というより抽象化軽視
ゼロコストという損得勘定に強く依存するよりは高コスト抽象化の方がマシ
と判断できなくなる
ゼロコストという損得勘定に強く依存するよりは高コスト抽象化の方がマシ
と判断できなくなる
488デフォルトの名無しさん
2024/06/29(土) 22:55:28.22ID:xDrSJDK+ >>469
それは単にライフタイムに不慣れなだけじゃないかなと思った
構造体に参照を含むのはよくあることでライフタイムパラメタを付けるだけ
あとは関数で参照を含むデータを返す時にどの引数に由来するかを指定することなどしかすべきことはない
慣れてしまうと大したことはしていないよね
そこでもし間違えて指定してしまっても違反があればコンパイラが必ずエラーとするので安心して大丈夫
では何故コンパイラが自動で指定(解釈)してくれないのか?というと、複数の参照に対して別扱いするかどうかや複数の関係指定など各自に方針の余地があるため
それは単にライフタイムに不慣れなだけじゃないかなと思った
構造体に参照を含むのはよくあることでライフタイムパラメタを付けるだけ
あとは関数で参照を含むデータを返す時にどの引数に由来するかを指定することなどしかすべきことはない
慣れてしまうと大したことはしていないよね
そこでもし間違えて指定してしまっても違反があればコンパイラが必ずエラーとするので安心して大丈夫
では何故コンパイラが自動で指定(解釈)してくれないのか?というと、複数の参照に対して別扱いするかどうかや複数の関係指定など各自に方針の余地があるため
489デフォルトの名無しさん
2024/06/29(土) 23:12:35.54ID:/LX7F2Md C/C++だとそのへんを脳内の方針で逸脱しないように人間が監視しないといけない
Rustは楽
Rustは楽
490デフォルトの名無しさん
2024/06/29(土) 23:26:59.72ID:PsPEDCdZ 固定長配列をスライスに、BoxをRcに変換すると抽象度は上がる
失敗するかもしれないパターンマッチは抽象度を下げる
コンパイル時または実行時エラーかもしれないborrowも抽象度を下げる
失敗するかもしれないパターンマッチは抽象度を下げる
コンパイル時または実行時エラーかもしれないborrowも抽象度を下げる
491デフォルトの名無しさん
2024/06/30(日) 02:58:29.53ID:CdZYHoVj492デフォルトの名無しさん
2024/06/30(日) 03:44:32.65ID:K2J9qaLk493デフォルトの名無しさん
2024/06/30(日) 05:54:25.07ID:WATrci3L >>309
横からすみません。
C#を関数型っぽく書いたら、ここまではなったのでRustだったらどうなるのか聞いても良いでしょうか?
public static void Main(string[] args) { args.ToList().ForEach(f); }
static void f(string fileName)
{
Console.WriteLine(fileName);
File.ReadAllLines(fileName).Select(g).ToList().ForEach(Console.WriteLine);
}
static Func<string,int,string> g = (line,i) => $"{i + 1,2}:{line}";
横からすみません。
C#を関数型っぽく書いたら、ここまではなったのでRustだったらどうなるのか聞いても良いでしょうか?
public static void Main(string[] args) { args.ToList().ForEach(f); }
static void f(string fileName)
{
Console.WriteLine(fileName);
File.ReadAllLines(fileName).Select(g).ToList().ForEach(Console.WriteLine);
}
static Func<string,int,string> g = (line,i) => $"{i + 1,2}:{line}";
494デフォルトの名無しさん
2024/06/30(日) 09:33:23.06ID:L3wyoKVN どうもならんよ
495デフォルトの名無しさん
2024/06/30(日) 10:12:23.11ID:BLjMhwlM リファクタリングのすごさは、外側から見たら何も変化しないことだからね
496デフォルトの名無しさん
2024/06/30(日) 10:30:41.18ID:8eFU1ITU497デフォルトの名無しさん
2024/06/30(日) 10:53:06.05ID:DQMdIUg4 あえて >>493 で頑張ると
https://paiza.io/projects/sk40IXUgPm0k_VgI1wsHBg
fn main() {
let cwln = |s| { println!("{}", s) };
let g = |(i, line): (usize, &str)| { format!("{:>2}:{}", i + 1, line) };
let f = |file_name: String| {
cwln(file_name.clone());
std::fs::read_to_string(file_name).map(|u8b| {
u8b.lines().enumerate().map(g).for_each(cwln)
}).unwrap()
};
std::env::args().skip(1).for_each(f)
}
https://paiza.io/projects/sk40IXUgPm0k_VgI1wsHBg
fn main() {
let cwln = |s| { println!("{}", s) };
let g = |(i, line): (usize, &str)| { format!("{:>2}:{}", i + 1, line) };
let f = |file_name: String| {
cwln(file_name.clone());
std::fs::read_to_string(file_name).map(|u8b| {
u8b.lines().enumerate().map(g).for_each(cwln)
}).unwrap()
};
std::env::args().skip(1).for_each(f)
}
498デフォルトの名無しさん
2024/06/30(日) 10:54:12.53ID:BLjMhwlM do記法のたぐいはラムダで実装しても命令型で実装してもどっちでもいい
外側から見れば同じだからだ
外側から見れば同じだからだ
499デフォルトの名無しさん
2024/06/30(日) 11:17:03.52ID:msuugTQH >>496
.net標準にはList型にしかForEachが導入されてないからやな。
C#ではチェインメソッドにしないほうがいいとされてる。
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/foreach-vs-foreach
.net標準にはList型にしかForEachが導入されてないからやな。
C#ではチェインメソッドにしないほうがいいとされてる。
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/foreach-vs-foreach
500デフォルトの名無しさん
2024/06/30(日) 12:31:43.09ID:NR+aRvdr >>499
「.ForEachしたいけど標準にないからToListする」という考え方が間違い
enumerable.ToList().ForEach()のパターンは最悪
それとそのEric Rippertの意見がMSやC#コミュニティのコンセンサスというわけではないよ
IEnumerable以外ではForEach等の副作用適用メソッドが標準で用意されてるものが多々あるしIEnumerableに拡張メソッド追加して使ってるところもごまんとある
「.ForEachしたいけど標準にないからToListする」という考え方が間違い
enumerable.ToList().ForEach()のパターンは最悪
それとそのEric Rippertの意見がMSやC#コミュニティのコンセンサスというわけではないよ
IEnumerable以外ではForEach等の副作用適用メソッドが標準で用意されてるものが多々あるしIEnumerableに拡張メソッド追加して使ってるところもごまんとある
501デフォルトの名無しさん
2024/06/30(日) 13:08:54.78ID:7wkc/L2e >>497
キツイ
キツイ
502デフォルトの名無しさん
2024/06/30(日) 13:13:35.11ID:6LaDfHu1503デフォルトの名無しさん
2024/06/30(日) 13:41:54.85ID:L3wyoKVN unwarpほんま糞ダサい
504デフォルトの名無しさん
2024/06/30(日) 14:01:03.54ID:BLjMhwlM 「すべてはオブジェクトである」が糞ダサいのだ
いい感じの構文糖はたいていオブジェクトではない
いい感じの構文糖はたいていオブジェクトではない
505デフォルトの名無しさん
2024/06/30(日) 15:34:51.28ID:iQS10/oI506デフォルトの名無しさん
2024/06/30(日) 16:34:51.56ID:WATrci3L507デフォルトの名無しさん
2024/06/30(日) 16:49:10.64ID:MSv8cbxu Rustで関数型のように書くなら
use std::env;
use std::fs::File;
use std::io::{self, BufRead, BufReader};
fn main() -> io::Result<()> {
env::args()
.skip(1)
.inspect(|file_name| println!("{file_name}"))
.map(|file_name| {
File::open(file_name).and_then(|file| {
BufReader::new(file)
.lines()
.enumerate()
.map(|(i, line)| line.map(|line| println!("{}: {line}", i + 1)))
.collect()
})
})
.collect()
}
use std::env;
use std::fs::File;
use std::io::{self, BufRead, BufReader};
fn main() -> io::Result<()> {
env::args()
.skip(1)
.inspect(|file_name| println!("{file_name}"))
.map(|file_name| {
File::open(file_name).and_then(|file| {
BufReader::new(file)
.lines()
.enumerate()
.map(|(i, line)| line.map(|line| println!("{}: {line}", i + 1)))
.collect()
})
})
.collect()
}
508デフォルトの名無しさん
2024/06/30(日) 16:59:35.48ID:WATrci3L 質問です。
.map(|(i, line)| line.map(|line| println!("{}: {line}", i + 1)))
↑
line.mapは文字列へのmapで1文字1文字に番号振ってる様に見えますが、違うのでしょうか?
素直に
.map(|(i, line)| println!("{}: {line}", i + 1))
とは出来ないのでしょうか?
.map(|(i, line)| line.map(|line| println!("{}: {line}", i + 1)))
↑
line.mapは文字列へのmapで1文字1文字に番号振ってる様に見えますが、違うのでしょうか?
素直に
.map(|(i, line)| println!("{}: {line}", i + 1))
とは出来ないのでしょうか?
509デフォルトの名無しさん
2024/06/30(日) 17:13:06.42ID:MSv8cbxu510デフォルトの名無しさん
2024/06/30(日) 17:55:47.01ID:2aLeyJWV こうやって関数型を勘違いしたやつが量産されてるんだな
511デフォルトの名無しさん
2024/06/30(日) 18:10:42.55ID:WATrci3L512デフォルトの名無しさん
2024/06/30(日) 18:12:41.76ID:aILYkgH6 さすが二つ名持ちの汚コーダー
ひと味もふた味も違う
ひと味もふた味も違う
513デフォルトの名無しさん
2024/06/30(日) 18:28:40.79ID:MSv8cbxu 関数型のように書きたいならば基本はfor_eachを使わない
行き詰まりのfor_eachを使うと値もエラーも返せなくなる
行き詰まりのfor_eachを使うと値もエラーも返せなくなる
514デフォルトの名無しさん
2024/06/30(日) 18:46:14.08ID:DeiuUcf0515デフォルトの名無しさん
2024/06/30(日) 20:38:10.26ID:oQ6wZd+v let a: [u32; 4] = [1, 2, 3, 4];
let s: &[u32] = &a[1..3];
a[5]; と書くとコンパイルエラーが発生しますが、
s[5]; と書くとコンパイルは通り実行時にエラーが発生します。
なぜ、 s[5]; が範囲外の領域へのアクセスであることをコンパイル時に見抜けないのでしょうか?
本を見ても、理由が書いてないです。
ただ、そうなるとしか書いてありません。
let s: &[u32] = &a[1..3];
a[5]; と書くとコンパイルエラーが発生しますが、
s[5]; と書くとコンパイルは通り実行時にエラーが発生します。
なぜ、 s[5]; が範囲外の領域へのアクセスであることをコンパイル時に見抜けないのでしょうか?
本を見ても、理由が書いてないです。
ただ、そうなるとしか書いてありません。
516デフォルトの名無しさん
2024/06/30(日) 21:21:34.70ID:aS5UFAEb 見抜けるようになっていないから
a は array である一方で s は slice
array は型として長さの情報を持つ一方 slice は持たない
slice の長さはコンパイル時にわからないしわかろうともしないしチェックもない
a は array である一方で s は slice
array は型として長さの情報を持つ一方 slice は持たない
slice の長さはコンパイル時にわからないしわかろうともしないしチェックもない
517デフォルトの名無しさん
2024/06/30(日) 21:23:59.76ID:MSv8cbxu >>515
静的にサイズが定数だと静的に比較できるから事前にコンパイルエラーとなる
配列は静的にサイズが定数
スライスもこのように静的にサイズを定数にしてやれば事前にコンパイルエラーとなる
const X: &[u32] = &[1, 2, 3, 4];
let x = X[5];
静的にサイズが定数だと静的に比較できるから事前にコンパイルエラーとなる
配列は静的にサイズが定数
スライスもこのように静的にサイズを定数にしてやれば事前にコンパイルエラーとなる
const X: &[u32] = &[1, 2, 3, 4];
let x = X[5];
518デフォルトの名無しさん
2024/06/30(日) 21:57:28.27ID:6Q+TlIxj 🦀🦀🦀
519デフォルトの名無しさん
2024/06/30(日) 22:10:02.00ID:BLjMhwlM 本といえども一方通行のメディアではなくなってるんじゃないか
読者の側がそれをどうしても知りたい気持ちを表明しなければならないのが双方向でしょ
読者の側がそれをどうしても知りたい気持ちを表明しなければならないのが双方向でしょ
520デフォルトの名無しさん
2024/06/30(日) 22:48:34.24ID:NrRL076G >>513
一体全体何を言ってるんだ?
一体全体何を言ってるんだ?
521デフォルトの名無しさん
2024/06/30(日) 23:09:55.43ID:MSv8cbxu522デフォルトの名無しさん
2024/07/01(月) 00:45:59.76ID:d9FHgeU6 >>521
>for_eachは値を返せない
for_eachはunitを返してるよ
>関数は基本的に値やエラーを返す
voidやunitやnilを返すものも関数だよ
>イテレータ利用で値やエラーを返すためにはfor_eachではなくcollectやfoldなどを用いる
try_for_each使ってね
file openやprintのような副作用をイテレータのmapで行うのは関数型の考え方からは程遠いよ
>for_eachは値を返せない
for_eachはunitを返してるよ
>関数は基本的に値やエラーを返す
voidやunitやnilを返すものも関数だよ
>イテレータ利用で値やエラーを返すためにはfor_eachではなくcollectやfoldなどを用いる
try_for_each使ってね
file openやprintのような副作用をイテレータのmapで行うのは関数型の考え方からは程遠いよ
523デフォルトの名無しさん
2024/07/01(月) 01:02:37.18ID:3Woy0c9R 値を()しか返せないのでは意味がない
524デフォルトの名無しさん
2024/07/01(月) 01:19:54.94ID:CgZJmBCn お前の人生よりは意味あるよ
525デフォルトの名無しさん
2024/07/01(月) 04:16:03.32ID:VTE9nWpJ unwrapをmapで代用とかセンス無さ過ぎ
526デフォルトの名無しさん
2024/07/01(月) 05:26:16.34ID:WAZyoaEd 見抜いたことを全て警告するコンパイラがあったらこんな感じになるのか
527デフォルトの名無しさん
2024/07/01(月) 05:49:45.95ID:ppYg1fh2 Rustは清書用(キリっ
528デフォルトの名無しさん
2024/07/01(月) 05:51:10.72ID:D/wxxrcg 犯人不明ボイス・トォ・スカル被害者にしている者皆判明
AIで被害者が苦しんでいる映像を作成してそれで喜んでいる脳細胞を読み取れば使用しているかの判定
AIで自分が高みの見物ができるかどうかも判定
あとは下記を参考にして行えばよい
いじめで殺害したかも判明するので迷宮入り事件犯人を絞り込める
隠しカメラの場所も判明
忘れた記憶を再び思い出せるようにする脳細胞を発見!
2024.06.28
「あなたの一番古い記憶は?」人は覚えていても2歳以前の記憶にアクセスできなくなっている
2023.11.30
なぜ私たちは起こってもいない間違った記憶をしてしまうのか?
2023.11.27
自分でも気づいていない「記憶の間違い」を脳波で判断できると判明
2023.10.19
富山大、睡眠中の脳で行われている推論の演算を神経細胞レベルで解明
2024/06/26
サイコパスはためらわない?−−嘘つきの脳のメカニズム
2019/09/26
脳を刺激して特定の記憶を呼び戻す技術「記憶プロテーゼ」を開発
2024/02/21
「0」を”思う”ときの脳活動は「1」に近い!捕食者への恐怖がゼロの根幹だった?
2024.03.07
>>MEGを使うと、脳内でわずかに発生する磁場変化をとらえて、脳活動を記録することが可能です。
>>(※脳波計が脳の電気活動を読み取るのに対して、脳磁計は脳の磁気活動を読み取ります)
東工大、磁束集中器を用いない高感度「ダイヤモンド量子センサ」を開発
2024/06/07
>>日常的な検診や脳機能のより詳しい研究や、ブレイン・マシン・インタフェースの研究などへ大きく貢献できると期待されている。
AIで被害者が苦しんでいる映像を作成してそれで喜んでいる脳細胞を読み取れば使用しているかの判定
AIで自分が高みの見物ができるかどうかも判定
あとは下記を参考にして行えばよい
いじめで殺害したかも判明するので迷宮入り事件犯人を絞り込める
隠しカメラの場所も判明
忘れた記憶を再び思い出せるようにする脳細胞を発見!
2024.06.28
「あなたの一番古い記憶は?」人は覚えていても2歳以前の記憶にアクセスできなくなっている
2023.11.30
なぜ私たちは起こってもいない間違った記憶をしてしまうのか?
2023.11.27
自分でも気づいていない「記憶の間違い」を脳波で判断できると判明
2023.10.19
富山大、睡眠中の脳で行われている推論の演算を神経細胞レベルで解明
2024/06/26
サイコパスはためらわない?−−嘘つきの脳のメカニズム
2019/09/26
脳を刺激して特定の記憶を呼び戻す技術「記憶プロテーゼ」を開発
2024/02/21
「0」を”思う”ときの脳活動は「1」に近い!捕食者への恐怖がゼロの根幹だった?
2024.03.07
>>MEGを使うと、脳内でわずかに発生する磁場変化をとらえて、脳活動を記録することが可能です。
>>(※脳波計が脳の電気活動を読み取るのに対して、脳磁計は脳の磁気活動を読み取ります)
東工大、磁束集中器を用いない高感度「ダイヤモンド量子センサ」を開発
2024/06/07
>>日常的な検診や脳機能のより詳しい研究や、ブレイン・マシン・インタフェースの研究などへ大きく貢献できると期待されている。
529デフォルトの名無しさん
2024/07/01(月) 06:29:11.19ID:XAeGvvJG >>525
unwrapは使わずにmapでNone/Errを透過的に渡すのはRustの基本
unwrapは使わずにmapでNone/Errを透過的に渡すのはRustの基本
530デフォルトの名無しさん
2024/07/01(月) 07:19:14.88ID:WAZyoaEd これmapメソッドでもmap関数でもない中立な勢力が勝つパターンだ
531デフォルトの名無しさん
2024/07/01(月) 11:47:54.40ID:LZ9kVfeK Functorのmapなんだよね
でもFunctorは定義されてなくて統一的に扱えないんだから
Result/Optionはfmapとか違う名前にしておいたほうがよかったと思う
どっちにしろmap/fmapで副作用はアンチパターン
でもFunctorは定義されてなくて統一的に扱えないんだから
Result/Optionはfmapとか違う名前にしておいたほうがよかったと思う
どっちにしろmap/fmapで副作用はアンチパターン
532デフォルトの名無しさん
2024/07/01(月) 11:55:40.56ID:14Z1Ksgh fmapなんかflatMapと勘違いされるだろ
533デフォルトの名無しさん
2024/07/01(月) 12:47:47.85ID:Z0Kzqg/U そんな勘違いをする人にRustは無理
534デフォルトの名無しさん
2024/07/01(月) 12:59:53.25ID:irzLgX5l >>525
こう書くとresultがErrの時に返せずここでpanicになってしまう
let val = result.unwrap();
f(val)
そのためpanicしてもいいとか絶対にErrとならない特殊な場合を除けば
unwrapを用いてはダメでmapを使ってこのように書くんだよ
result.map(|val| f(val))
ここで本当に関数fを呼ぶだけならresult.map(f)と簡略化できるけど
f(val)の部分は式やブロックの可能性もあるので簡略化せずに進めるね
これは以下と同等でErr(err)の時に保持してくれている
match result {
Ok(val) => Ok(f(val)),
Err(err) => Err(err),
}
ちなみにf(val)もResultを返すときは
mapの代わりにand_thenがある
result.and_then(|val| f(val))
つまり以下の二つは同等
result.map(|val| f(val))
result.and_then(|val| Ok(f(val)))
この場合はもちろん簡素なmapを用いるべき
こう書くとresultがErrの時に返せずここでpanicになってしまう
let val = result.unwrap();
f(val)
そのためpanicしてもいいとか絶対にErrとならない特殊な場合を除けば
unwrapを用いてはダメでmapを使ってこのように書くんだよ
result.map(|val| f(val))
ここで本当に関数fを呼ぶだけならresult.map(f)と簡略化できるけど
f(val)の部分は式やブロックの可能性もあるので簡略化せずに進めるね
これは以下と同等でErr(err)の時に保持してくれている
match result {
Ok(val) => Ok(f(val)),
Err(err) => Err(err),
}
ちなみにf(val)もResultを返すときは
mapの代わりにand_thenがある
result.and_then(|val| f(val))
つまり以下の二つは同等
result.map(|val| f(val))
result.and_then(|val| Ok(f(val)))
この場合はもちろん簡素なmapを用いるべき
535デフォルトの名無しさん
2024/07/01(月) 13:41:34.54ID:JlB5uk0q Rustを10年以上使ってるひとに質問です
Rust本体をバージョンアップしたときに
動かなくなった旧バージョン用のcratesや自分のプロジェクト(main.rsなど)は
どれくらいありましたか?
またdeprecatedやobsoletedにされた機能は
使えなくなるまでに実際何年くらい使い続けられましたか?
Rust本体をバージョンアップしたときに
動かなくなった旧バージョン用のcratesや自分のプロジェクト(main.rsなど)は
どれくらいありましたか?
またdeprecatedやobsoletedにされた機能は
使えなくなるまでに実際何年くらい使い続けられましたか?
536デフォルトの名無しさん
2024/07/01(月) 14:05:59.07ID:/HpLpXor Rust 1.0からまだ10年経っていない
Rustは3年毎のedition制度があって後方互換性がない変化はeditionが変わるため安心
今も最初のRust 2015 editionがサポートされてる
さらにedition移行支援ツールもある
Rustは他言語と比べてかなり恵まれてる良い環境
Rustは3年毎のedition制度があって後方互換性がない変化はeditionが変わるため安心
今も最初のRust 2015 editionがサポートされてる
さらにedition移行支援ツールもある
Rustは他言語と比べてかなり恵まれてる良い環境
537デフォルトの名無しさん
2024/07/01(月) 14:11:38.44ID:JlB5uk0q >>534
>ちなみにf(val)もResultを返すときは
の条件なら
>つまり以下の二つは同等
> result.map(|val| f(val)) // Resultを還さないf
> result.and_then(|val| f(val)) // Resultを還すf
じゃないんですかね(Ok(f(val))は蛇足)
>ちなみにf(val)もResultを返すときは
の条件なら
>つまり以下の二つは同等
> result.map(|val| f(val)) // Resultを還さないf
> result.and_then(|val| f(val)) // Resultを還すf
じゃないんですかね(Ok(f(val))は蛇足)
538デフォルトの名無しさん
2024/07/01(月) 14:22:14.04ID:seu0xN2c Resultを返すか返さないか関係なくこれは常に成り立つね
>>534
> 以下の二つは同等
> result.map(|val| f(val))
> result.and_then(|val| Ok(f(val)))
例えばf(val)がOptionを返したとしても成立するよ
>>534
> 以下の二つは同等
> result.map(|val| f(val))
> result.and_then(|val| Ok(f(val)))
例えばf(val)がOptionを返したとしても成立するよ
539デフォルトの名無しさん
2024/07/01(月) 14:22:38.11ID:14Z1Ksgh flat_map の関数名を and_then にしたのはどこの言語の文化?
540デフォルトの名無しさん
2024/07/01(月) 14:43:32.98ID:WAZyoaEd iostreamの記号をまるでセガサターンのように見下して英単語を推した文化
541デフォルトの名無しさん
2024/07/01(月) 14:48:54.46ID:JlB5uk0q and_thenはor_elseに対してのantitheseだと思った
542デフォルトの名無しさん
2024/07/01(月) 14:51:31.68ID:seu0xN2c result1.and(result2) がまずあって
result1.and_then(|ok1| return_result2(ok1)) が関数版だね
OptionでもResultでも同じ命名
result1.and_then(|ok1| return_result2(ok1)) が関数版だね
OptionでもResultでも同じ命名
543デフォルトの名無しさん
2024/07/01(月) 14:59:21.90ID:3i64JhgU iostreamの << をRustに導入しなかったのはなぜ?
544デフォルトの名無しさん
2024/07/01(月) 15:05:11.12ID:kC5U6Id4 std::fmtで十分だから
545デフォルトの名無しさん
2024/07/01(月) 15:05:34.52ID:YDWAPNrm うるせぇやりたきゃShl実装しろ
546デフォルトの名無しさん
2024/07/01(月) 15:30:41.32ID:wNG1bhSA >>543
単純な二項演算子でやると書式指定の範囲を制御できないんだよ。
C++ ではストリームに対する書式指定は永続的な効果を持っていて、その効果を上書きするまで続く。
普通の方法で指定したらグローバルな影響を持ってしまうのは明らかにまずい。
iostream が出来たときは可変長引数の関数を型安全に扱う方法 (variadic template) が無かったし、
書式指定文字列をコンパイル時に解釈して安全に扱う方法 (constexpr) も無かったから
その範囲内で当時の知見で比較的マシな形にしたらああなったという程度のもんで、
今の考え方からすると iostream は真似したいようなもんじゃない。
むしろ C++ のほうが新しい仕様では Rust 風のやり方に寄せて来てる。
単純な二項演算子でやると書式指定の範囲を制御できないんだよ。
C++ ではストリームに対する書式指定は永続的な効果を持っていて、その効果を上書きするまで続く。
普通の方法で指定したらグローバルな影響を持ってしまうのは明らかにまずい。
iostream が出来たときは可変長引数の関数を型安全に扱う方法 (variadic template) が無かったし、
書式指定文字列をコンパイル時に解釈して安全に扱う方法 (constexpr) も無かったから
その範囲内で当時の知見で比較的マシな形にしたらああなったという程度のもんで、
今の考え方からすると iostream は真似したいようなもんじゃない。
むしろ C++ のほうが新しい仕様では Rust 風のやり方に寄せて来てる。
547デフォルトの名無しさん
2024/07/01(月) 15:53:07.19ID:2HyCglUW >>543
ダサすぎるから
ダサすぎるから
548デフォルトの名無しさん
2024/07/01(月) 15:56:35.04ID:iVgAAf6K rustもprint時のstring interpolationはもう少しどうにかならんものかね
549デフォルトの名無しさん
2024/07/01(月) 18:51:52.61ID:r9fpSp0F macroなんで自分で描き替えればええんやで
550デフォルトの名無しさん
2024/07/01(月) 20:45:22.07ID:WAZyoaEd 自作した後の自己肯定を10年続けるまでがプログラム技術
551デフォルトの名無しさん
2024/07/01(月) 23:04:21.05ID:3i64JhgU 昔、C++でprintf使ったら怖い人に怒られたのに
今じゃあれはクソ設計だったって評価に固まってるんだね、英語圏でも
今じゃあれはクソ設計だったって評価に固まってるんだね、英語圏でも
552デフォルトの名無しさん
2024/07/01(月) 23:12:10.92ID:wNG1bhSA >>551
C/C++ の printf は iostream 以上にカス。
型のチェックがガバガバだし、ちゃんと理解してないやつのほうが多いので常に問題を引き起こしていた。
ただ、記法としてはこれで良かった。
C/C++ の printf は iostream 以上にカス。
型のチェックがガバガバだし、ちゃんと理解してないやつのほうが多いので常に問題を引き起こしていた。
ただ、記法としてはこれで良かった。
553デフォルトの名無しさん
2024/07/02(火) 02:06:02.53ID:bkJ9zxrb 今の C/C++ の printf はコンパイル時に型チェックして警告してくれる
554デフォルトの名無しさん
2024/07/02(火) 05:00:17.05ID:VNjymWLQ555デフォルトの名無しさん
2024/07/02(火) 06:06:14.65ID:wHmBy3hI >>554
みえる、じゃなくて完全に遺物だろ
みえる、じゃなくて完全に遺物だろ
556デフォルトの名無しさん
2024/07/02(火) 06:44:02.90ID:VNjymWLQ 表示はRustのDisplayトレイト実装方式が洗練されていて使いやすくていいね
557デフォルトの名無しさん
2024/07/02(火) 08:28:24.43ID:UD4Nu927 仕様書が聖書のようなものだから遺物だろうが仕様書に逆らうわけにはいかないじゃん
558デフォルトの名無しさん
2024/07/02(火) 08:41:47.20ID:hGRi0mb2 >>544
C の関数は基本的にはちゃんと型はついてるが可変長引数は静的な型情報を捨てること実現してる。
もちろんそれを引き継いだ C++ も。
C++ は後に variadic template による安全な可変長引数を導入したが古いスタイルの可変長引数も廃止はしてない。
言語仕様を素朴に実装したら型はわからないんだよ。
printf などの一部の関数に限っては「関数の型情報によらずに」コンパイラが特別扱いでチェックしてる。
関数の型を元に検査してるんじゃなくて printf の仕様をビルトインして特別扱いしてるの。
C の関数は基本的にはちゃんと型はついてるが可変長引数は静的な型情報を捨てること実現してる。
もちろんそれを引き継いだ C++ も。
C++ は後に variadic template による安全な可変長引数を導入したが古いスタイルの可変長引数も廃止はしてない。
言語仕様を素朴に実装したら型はわからないんだよ。
printf などの一部の関数に限っては「関数の型情報によらずに」コンパイラが特別扱いでチェックしてる。
関数の型を元に検査してるんじゃなくて printf の仕様をビルトインして特別扱いしてるの。
559デフォルトの名無しさん
2024/07/02(火) 10:27:11.96ID:LnXo4/R2 >>538
result.and_then(|val| Ok(f(val)?))
とか
result.and_then(|val| Ok(f(val).unwrap()))
じゃなくて
result.and_then(|val| Ok(f(val)))
で良いのはなぜ?
result.and_then(|val| Ok(f(val)?))
とか
result.and_then(|val| Ok(f(val).unwrap()))
じゃなくて
result.and_then(|val| Ok(f(val)))
で良いのはなぜ?
560デフォルトの名無しさん
2024/07/02(火) 10:37:23.15ID:tsLlTVbC Rust初めて使ったときは「println! みたいな基本的なものがマクロで?大丈夫かこの言語」みたいに思ったもんだが、
よくよく考えるとマクロにせずに、柔軟なシグニチャでなんとかしようとする他の言語のほうがよっぽど醜いもんな。
よくよく考えるとマクロにせずに、柔軟なシグニチャでなんとかしようとする他の言語のほうがよっぽど醜いもんな。
561デフォルトの名無しさん
2024/07/02(火) 10:55:15.33ID:/ZI4FWA6562デフォルトの名無しさん
2024/07/02(火) 11:50:20.39ID:hGRi0mb2 >>560
C++ のライトユーザは関数テンプレートのことを誤ってテンプレート関数と呼ぶことが頻繁にある。
関数テンプレートが関数であるという誤解が言葉になって表れてるんだと思う。
単に使うだけなら関数みたいに見えてしまうからかもしれない。
関数テンプレートは関数を生成する元になるテンプレートだから関数テンプレートなので「生成する」というところに着目したらマクロで生成するのでも理屈はあまり変わらないかもしれない。
ただ、 LISP 系言語の経験から言うと構文レベルで制御されるマクロはエディタのサポートが受けづらいし、ドキュメントを型で表現できないのはやりづらい。
マクロ展開の失敗がどういう失敗なのかをきちんとエラーメッセージにするのも難しい。
デメリットもあるけど、どうせどこかに問題があるならこのくらいで良いという潔さは感じる。
C++ のライトユーザは関数テンプレートのことを誤ってテンプレート関数と呼ぶことが頻繁にある。
関数テンプレートが関数であるという誤解が言葉になって表れてるんだと思う。
単に使うだけなら関数みたいに見えてしまうからかもしれない。
関数テンプレートは関数を生成する元になるテンプレートだから関数テンプレートなので「生成する」というところに着目したらマクロで生成するのでも理屈はあまり変わらないかもしれない。
ただ、 LISP 系言語の経験から言うと構文レベルで制御されるマクロはエディタのサポートが受けづらいし、ドキュメントを型で表現できないのはやりづらい。
マクロ展開の失敗がどういう失敗なのかをきちんとエラーメッセージにするのも難しい。
デメリットもあるけど、どうせどこかに問題があるならこのくらいで良いという潔さは感じる。
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 中国の局長は「両手をポケット」で対峙 宣伝戦で国民に示す ★3 [蚤の市★]
- 日本行き空路49万件キャンセル 中国自粛呼びかけ 日本行きチケット予約の約32%に相当 ★4 [ぐれ★]
- 中国側が首相答弁の撤回要求、日本側拒否 [夜のけいちゃん★]
- 映画「鬼滅の刃」の興行収入急減、日本行き航空券大量キャンセル…中国メディア報道 [蚤の市★]
- 【音楽】Perfume・あ~ちゃんの結婚相手「一般男性」は吉田カバンの社長・吉田幸裕氏(41) 高身長で山本耕史似 [Ailuropoda melanoleuca★]
- 「タワマン天国」に飛びつく若者…SNSに転がる「成功体験」に続けるのか 湾岸エリアの業者が語った現実 [蚤の市★]
- 【悲報】おこめ券、9.5億円配布分のうち2.4億が経費、うちJAが1億円中抜き🤗高市ありがとう [359965264]
- AV女優さん「時間停止物」のAVを完全否定してネット騒然。お前らの夢が1つ潰える [152212454]
- 【悲報】高市有事で日本に同調する国、1つも現れないwwwwwwwwwwwwwww [603416639]
- 自閉症が「んなっしょい」と連呼するお🏡
- FGOで好きなサーヴァントがアビゲイル、北斎、楊貴妃なんだが
- (´・ω・`)おはよ
