公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust
Web上の実行環境
https://play.rust-lang.org
日本語の情報
https://rust-jp.rs/
※Rustを学びたい人はまず最初に公式のThe Bookを読むこと
https://doc.rust-lang.org/book/
※Rustのasyncについて知りたければ「async-book」は必読
https://rust-lang.github.io/async-book/
※C++との比較は専用スレへ
C++ vs Rust
https://mevius.5ch.net/test/read.cgi/tech/1619219089/
※次スレは原則>>980が立てること
前スレ
Rust part12
https://mevius.5ch.net/test/read.cgi/tech/1629813327/
探検
Rust part13
■ このスレッドは過去ログ倉庫に格納されています
2021/11/07(日) 10:04:59.35ID:pJhT3MIE
140デフォルトの名無しさん
2021/11/26(金) 11:23:55.78ID:/IsoxS9R141デフォルトの名無しさん
2021/11/26(金) 11:31:53.80ID:oSCWFWAt >>140
はえ〜、そうか勉強になったわ
はえ〜、そうか勉強になったわ
142デフォルトの名無しさん
2021/11/26(金) 11:44:41.28ID:kuMbCEJE >>139
二重指定は一方でtrue一方でfalse指定しているパターン
二重指定は一方でtrue一方でfalse指定しているパターン
143デフォルトの名無しさん
2021/11/26(金) 12:05:35.16ID:SqSfLhr2144デフォルトの名無しさん
2021/11/26(金) 12:25:05.02ID:kuMbCEJE 通常のCのオープン関数のほうが100倍キレイで簡潔で合理的だと思うが個人差はあるんだろうな
File::options().read(true).create(true).open("foo.txt”);
これを書くときにリードがtrueだな、createもtrueだな、そしてファイル名はfoo.txtだと言う思考順序で
コード書くとは思えないんですよ常識的に
File::options().read(true).create(true).open("foo.txt”);
これを書くときにリードがtrueだな、createもtrueだな、そしてファイル名はfoo.txtだと言う思考順序で
コード書くとは思えないんですよ常識的に
145デフォルトの名無しさん
2021/11/26(金) 12:29:19.27ID:kuMbCEJE これが美しいと言う人はそれこそ逆ポーランド次元から来た異次元人だと思うよ
146デフォルトの名無しさん
2021/11/26(金) 12:40:54.22ID:R0yJ4Kup なかなか極端な例を出してきたな……
147デフォルトの名無しさん
2021/11/26(金) 12:43:09.59ID:GoGODfBQ148デフォルトの名無しさん
2021/11/26(金) 12:51:53.22ID:kuMbCEJE 逆ポーランド人現る
149デフォルトの名無しさん
2021/11/26(金) 12:53:26.61ID:kuMbCEJE ファイルを開こうと思うときにoptions型から思考がスタートする人は天才なんだろうな
それか飼いならされた人
それか飼いならされた人
150デフォルトの名無しさん
2021/11/26(金) 12:57:20.12ID:kuMbCEJE 言語否定じゃなくてライブラリ設計がおかしい
実用無視の人が設計するとこうなる
実用無視の人が設計するとこうなる
151デフォルトの名無しさん
2021/11/26(金) 12:58:29.05ID:Q6WyUjPa File::open_with_options("foo.txt", &OpenOptions::new().read(true).create(true));
どっちが良いとか悪いとかじゃないと思うがなあ
どっちが良いとか悪いとかじゃないと思うがなあ
152デフォルトの名無しさん
2021/11/26(金) 13:13:18.47ID:kuMbCEJE 美しくないだろ普通に
153デフォルトの名無しさん
2021/11/26(金) 13:13:45.37ID:HMe+psgI OpenOptionsって名前で明らかに「ファイル開く時のオプションですよ」って名前なのにファイル開く操作まで持ってるから気持ち悪いんだよな
同じモジュールでディレクトリはDirBuilderとかあるんだから普通にFileBuilderとかにすりゃええやんとか思っちゃうけどなんか理由があったんかね
同じモジュールでディレクトリはDirBuilderとかあるんだから普通にFileBuilderとかにすりゃええやんとか思っちゃうけどなんか理由があったんかね
154デフォルトの名無しさん
2021/11/26(金) 13:23:36.09ID:kuMbCEJE 確かに他だったらoptionのインスタンスを作ってopenに食わせる感じだな
それもどうかと思うけど
ほぼ定数みたいなものをわざわざ作って食わせるなんて
それもどうかと思うけど
ほぼ定数みたいなものをわざわざ作って食わせるなんて
155デフォルトの名無しさん
2021/11/26(金) 14:04:50.29ID:TIzT5fn9 慣れない人にとっては分かりにくいAPIにならざるを得ないのは確か
ただ他の言語でオプション引数やオーバーロードが2桁あるのが当たり前になってるようなライブラリを見るとそれぞれ一長一短あるなとは思う
ただ他の言語でオプション引数やオーバーロードが2桁あるのが当たり前になってるようなライブラリを見るとそれぞれ一長一短あるなとは思う
156デフォルトの名無しさん
2021/11/26(金) 14:15:29.08ID:Q6WyUjPa >>154
associated constくらい用意してもらってもいいかもね
associated constくらい用意してもらってもいいかもね
157デフォルトの名無しさん
2021/11/26(金) 14:20:28.16ID:Ye0bskEh158デフォルトの名無しさん
2021/11/26(金) 14:57:24.65ID:AxmLr4ZJ > 通常のCのオープン関数のほうが100倍キレイで簡潔で合理的
さっぱりわからんけどw
別に
File::options().readwrite().newfile().open("foo.txt”);
がいいとも悪いとも思わんし
cのopenがいいとも悪いとも思わん
どんな素晴らしいopen見せてくれるのかと思ったらガッカリした
さっぱりわからんけどw
別に
File::options().readwrite().newfile().open("foo.txt”);
がいいとも悪いとも思わんし
cのopenがいいとも悪いとも思わん
どんな素晴らしいopen見せてくれるのかと思ったらガッカリした
159デフォルトの名無しさん
2021/11/26(金) 15:03:20.08ID:BGloBCeB OpenOptionsが分かりにくいってのはそのとおりだと思うし、実際みんなそう思ってるみたいで
ちょうどFile::optionsにするRFCが通るところだよ
ちょうどFile::optionsにするRFCが通るところだよ
160デフォルトの名無しさん
2021/11/26(金) 16:18:02.52ID:Ye0bskEh >>159
stabilizeのPRが10日前に取り込まれたから1月にはリリースされそう
stabilizeのPRが10日前に取り込まれたから1月にはリリースされそう
161デフォルトの名無しさん
2021/11/26(金) 18:16:06.66ID:kuMbCEJE162デフォルトの名無しさん
2021/11/26(金) 19:18:40.42ID:wVYXipKz >>161
それはfopenの仕様(引数の意味とか)を知っているのが前提だからなぁ。
filenameとmodeの順番を間違えたら読み間違える。
メソッドチェーンと比較するなら名前付き引数のメソッド呼び出しじゃない?
あるいはインテリセンス環境下という条件付きか。
それはfopenの仕様(引数の意味とか)を知っているのが前提だからなぁ。
filenameとmodeの順番を間違えたら読み間違える。
メソッドチェーンと比較するなら名前付き引数のメソッド呼び出しじゃない?
あるいはインテリセンス環境下という条件付きか。
163デフォルトの名無しさん
2021/11/26(金) 19:21:46.75ID:Hq7eoo6P >>161
ほんそれ
ほんそれ
164デフォルトの名無しさん
2021/11/26(金) 19:26:21.35ID:kuMbCEJE 仮想のコードで例が適切かどうかわからないけど
File::options().readwrite().newfile().read().open("foo.txt”)
と書いて直後で書き込めねえええええよと叫ぶよりfopenの方がいいだろ;
File::options().readwrite().newfile().read().open("foo.txt”)
と書いて直後で書き込めねえええええよと叫ぶよりfopenの方がいいだろ;
165デフォルトの名無しさん
2021/11/26(金) 19:37:54.04ID:kuMbCEJE あ、ミスった
それはさておき例のメソッドチェーン見ても瞬時に不安しかよぎらない
readwrite() が中で read(true).write(true) してるとして
readonly() が中でread(true)しかしてないんじゃないかとか不安
それはさておき例のメソッドチェーン見ても瞬時に不安しかよぎらない
readwrite() が中で read(true).write(true) してるとして
readonly() が中でread(true)しかしてないんじゃないかとか不安
166デフォルトの名無しさん
2021/11/26(金) 19:47:03.96ID:AxmLr4ZJ167デフォルトの名無しさん
2021/11/26(金) 20:09:04.42ID:XtGzaRsE168デフォルトの名無しさん
2021/11/26(金) 20:37:35.34ID:kuMbCEJE169デフォルトの名無しさん
2021/11/26(金) 20:42:02.78ID:kuMbCEJE cのfopenはメソッドチェーンより簡潔だ
本当は他の言語のenumでいいんだけど
Open("rust.txt",FileMode.Open, FileAccess.Read)
これでバグは出ない
本当は他の言語のenumでいいんだけど
Open("rust.txt",FileMode.Open, FileAccess.Read)
これでバグは出ない
170デフォルトの名無しさん
2021/11/26(金) 20:55:25.49ID:R0yJ4Kup そんなに変わらへんやん、むしろuseで引き込む名前が増えて美しくないやん
171デフォルトの名無しさん
2021/11/26(金) 21:02:27.39ID:Ye0bskEh foo(true, false, true, false) や foo(None, None, None, Some(true)) みたいな呼び出しよりは100倍マシ
172デフォルトの名無しさん
2021/11/26(金) 22:47:08.22ID:r6ugNRE0 ところでreadwrite()とかnewfile()ってなんですか?
173デフォルトの名無しさん
2021/11/27(土) 00:09:21.90ID:riEP2Tv6 OpenOptionsの名称問題はともかく
なぜメソッドをチェーンさせているかというと理由は明白で
OpenOptionsExtトレイトをuseすると使えメソッドが拡張されて.mode()などが使えるようになるからだよ
なぜメソッドをチェーンさせているかというと理由は明白で
OpenOptionsExtトレイトをuseすると使えメソッドが拡張されて.mode()などが使えるようになるからだよ
174デフォルトの名無しさん
2021/11/27(土) 00:15:29.99ID:4eTYjVC9 パイプ演算子は |> いつ実装されるの?
175デフォルトの名無しさん
2021/11/27(土) 00:19:05.68ID:L+2AsAAt どうせ上のtimes()トレイト君でしょ
176デフォルトの名無しさん
2021/11/27(土) 00:42:49.16ID:w5eY7K13 チェーンの話なら、出来るだけチェーン派が多いけど.NETのLINQみたいになったら嫌?
それとも歓迎?LINQ形式のほうが分かりやすい。前の高階関数の話もそうだけど…
OpenOptionsはなんでもかんでもトレイトの弊害の気もする
articles =
from a in articles
orderby a.published descending
select new article_st;
https://github.com/StardustDL/Linq-in-Rust
let e: Vec<i32> = linq!(from p in x.clone(), where p <= &5, orderby -p, select p * 2).collect();
このプロジェクトはcloneしてしまうところがダサいが、MSが参画しているということはありうるわけで
それとも歓迎?LINQ形式のほうが分かりやすい。前の高階関数の話もそうだけど…
OpenOptionsはなんでもかんでもトレイトの弊害の気もする
articles =
from a in articles
orderby a.published descending
select new article_st;
https://github.com/StardustDL/Linq-in-Rust
let e: Vec<i32> = linq!(from p in x.clone(), where p <= &5, orderby -p, select p * 2).collect();
このプロジェクトはcloneしてしまうところがダサいが、MSが参画しているということはありうるわけで
177デフォルトの名無しさん
2021/11/27(土) 00:54:31.43ID:tWlgYd9Y >>173
元がこうだもんな
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
そしてunix以外にも対応するために
std::os::unix::fs::OpenOptionsExtへ分けたのだろう
このメソッドチェーンビルダー方式以外のAPIでは詰む
元がこうだもんな
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
そしてunix以外にも対応するために
std::os::unix::fs::OpenOptionsExtへ分けたのだろう
このメソッドチェーンビルダー方式以外のAPIでは詰む
178デフォルトの名無しさん
2021/11/27(土) 05:50:15.37ID:IOkCeWcH179デフォルトの名無しさん
2021/11/27(土) 09:55:26.18ID:sBo289Q7 >>174
rustは第一引数がselfの場合にメソッドのレシーバーになるのだから、実質パイプライン
rustは第一引数がselfの場合にメソッドのレシーバーになるのだから、実質パイプライン
180デフォルトの名無しさん
2021/11/27(土) 11:01:40.71ID:kX7QbhiL それはElixirと同じ「なんちゃってパイプライン」でメソッドチェーンが実現できるというだけでは。
ここで欲しいと言われているのは大元のF#のように自由関数やその部分適用が使えるパイプラインのことだろう。
ここで欲しいと言われているのは大元のF#のように自由関数やその部分適用が使えるパイプラインのことだろう。
181デフォルトの名無しさん
2021/11/27(土) 12:26:31.88ID:Xdw8IP3R 自由関数?
182デフォルトの名無しさん
2021/11/27(土) 14:14:35.41ID:A1VfIYPt 第一引数がselfとかじゃないやつのことじゃね
183デフォルトの名無しさん
2021/11/27(土) 15:58:50.40ID:lc2cVbH3 自由関数ってなんだっけ?
自由変数ならわかるんだけど
自由変数ならわかるんだけど
184デフォルトの名無しさん
2021/11/27(土) 15:59:45.03ID:Xdw8IP3R 定義を示してほしいわな
F#界隈にもRust界隈にも無い用語だし
F#界隈にもRust界隈にも無い用語だし
185デフォルトの名無しさん
2021/11/27(土) 16:36:46.11ID:kX7QbhiL 何気なく使ってたけど調べてみたらC++用語だったか。しかも日本じゃ「フリー関数」という表記の方が一般的なんだな。
メンバー関数(メソッド)ではない素の関数ということで。
メンバー関数(メソッド)ではない素の関数ということで。
186デフォルトの名無しさん
2021/11/27(土) 17:08:07.51ID:FtAU5QYE その意味ならElixirは自由関数も部分適用も使えると思うが・・・
187デフォルトの名無しさん
2021/11/27(土) 17:20:05.91ID:kX7QbhiL そっちか。
Elixirのパイプラインの使用例でよく見る形式が部分適用とは違うんで使えないものと思っていた。すまん。
部分適用は別の表記になるんだな。
Elixirのパイプラインの使用例でよく見る形式が部分適用とは違うんで使えないものと思っていた。すまん。
部分適用は別の表記になるんだな。
188デフォルトの名無しさん
2021/11/27(土) 17:59:12.10ID:g2vJAoph C++でもフリー関数と言われたら free() のこと思い浮かべそうだが
189デフォルトの名無しさん
2021/11/27(土) 18:21:56.04ID:molZfSEM >>178
そうは言っても現状の下のこれが直感的に分かり易いとは思えないけど、、LINQはSQLとは関係ないよ。
whereとかselectがそれに見えるけど、言語的には直行性を高めた統合クエリなだけ
let mut y: Vec<i32> = x.clone().filter(|p| p <= &5).collect();
y.sort_by_key(|t| -t);
let y: Vec<i32> = y.into_iter().map(|t| t * 2).collect();
そうは言っても現状の下のこれが直感的に分かり易いとは思えないけど、、LINQはSQLとは関係ないよ。
whereとかselectがそれに見えるけど、言語的には直行性を高めた統合クエリなだけ
let mut y: Vec<i32> = x.clone().filter(|p| p <= &5).collect();
y.sort_by_key(|t| -t);
let y: Vec<i32> = y.into_iter().map(|t| t * 2).collect();
190デフォルトの名無しさん
2021/11/27(土) 19:30:03.08ID:tWlgYd9Y >>189
どこが見にくいのか具体的に教えて
use itertools::Itertools;
let y: Vec<i32> = x
.filter(|p| p <= &5)
.sorted_by_key(|t| -t)
.map(|t| t * 2)
.collect();
どこが見にくいのか具体的に教えて
use itertools::Itertools;
let y: Vec<i32> = x
.filter(|p| p <= &5)
.sorted_by_key(|t| -t)
.map(|t| t * 2)
.collect();
191デフォルトの名無しさん
2021/11/27(土) 21:12:33.33ID:VfaT4D+K192デフォルトの名無しさん
2021/11/27(土) 21:19:49.42ID:w2+KtZN6193デフォルトの名無しさん
2021/11/27(土) 21:31:03.67ID:w2+KtZN6 Herb Sutterという馬鹿も使ってるな。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4165.pdf
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4165.pdf
194デフォルトの名無しさん
2021/11/27(土) 21:39:57.32ID:VfaT4D+K 規格の上ではまだ見つけられないが
https://timsong-cpp.github.io/cppwp/n3337/over.match.oper#tab:over.rel.op.func
member function
non-member function
という当然の名称が出てきている
日本語版の規格分かる人「フリー関数」とやらを引用してくだしあ
https://timsong-cpp.github.io/cppwp/n3337/over.match.oper#tab:over.rel.op.func
member function
non-member function
という当然の名称が出てきている
日本語版の規格分かる人「フリー関数」とやらを引用してくだしあ
195デフォルトの名無しさん
2021/11/27(土) 21:43:56.78ID:w2+KtZN6 規格で定義された用語というより業界用語的なもんでないの
https://github.com/cpprefjp/site/issues/171
https://github.com/cpprefjp/site/issues/171
196デフォルトの名無しさん
2021/11/27(土) 21:44:30.32ID:lc2cVbH3 馬鹿っていちいち言うなよ
素直になれや
素直になれや
197デフォルトの名無しさん
2021/11/27(土) 22:07:33.35ID:tWlgYd9Y その「フリー関数」とはクラスのメンバー関数ではない非メンバー関数として
クラスのないRustではその非メンバー関数の定義はどうなるの?
例えば以下のprint_all()は適当に作ったトレイトPrintAllのメンバーかもしれないけど
現実には('a'..='z').print_all();が動作してしまうわけで『誰のメンバー関数』なの?それとも非メンバー関数?
trait PrintAll<T> {
fn print_all(self);
}
impl<I: Iterator<Item=T>, T: Display> PrintAll<T> for I {
fn print_all(self: I) {
self.for_each(|x| println!("{}", x));
}
}
クラスのないRustではその非メンバー関数の定義はどうなるの?
例えば以下のprint_all()は適当に作ったトレイトPrintAllのメンバーかもしれないけど
現実には('a'..='z').print_all();が動作してしまうわけで『誰のメンバー関数』なの?それとも非メンバー関数?
trait PrintAll<T> {
fn print_all(self);
}
impl<I: Iterator<Item=T>, T: Display> PrintAll<T> for I {
fn print_all(self: I) {
self.for_each(|x| println!("{}", x));
}
}
198デフォルトの名無しさん
2021/11/27(土) 22:20:27.30ID:w2+KtZN6 第一引数がselfである関数(メソッド)を自由関数として呼び出すことはできるけどその逆は真ではないってことじゃないかな。
https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax
https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax
199デフォルトの名無しさん
2021/11/27(土) 22:24:30.93ID:dpgg2nfE メソッド呼び出しできない関数は「フリー関数」ってことでええんちゃう?
非メンバ関数って呼ぶほうが断然一般的だとは思うが
非メンバ関数って呼ぶほうが断然一般的だとは思うが
200デフォルトの名無しさん
2021/11/27(土) 22:47:33.66ID:riEP2Tv6201デフォルトの名無しさん
2021/11/27(土) 23:15:00.42ID:udgmz45E https://dev.to/mindflavor/rust-builder-pattern-with-types-3chf
この手のPhantomDataとジェネリクス使って特定の条件満たした状態じゃないとbuildとかのメソッドが実装されないようにしたりしたビルダーパターンってここの人たちはどう思ってる?
説明だけ見るとめっちゃ良いやん!って思うけどいざ自分で書くとメリットに対して無駄に複雑&使う側としてもエラーが見にくいとかなんか微妙に感じちゃう
この手のPhantomDataとジェネリクス使って特定の条件満たした状態じゃないとbuildとかのメソッドが実装されないようにしたりしたビルダーパターンってここの人たちはどう思ってる?
説明だけ見るとめっちゃ良いやん!って思うけどいざ自分で書くとメリットに対して無駄に複雑&使う側としてもエラーが見にくいとかなんか微妙に感じちゃう
202デフォルトの名無しさん
2021/11/28(日) 00:27:08.53ID:j8Nrs0jp >>200
例えばこのように任意の実装が出来るからprint_all()はIteratorのメンバーではなくあくまでもPrintAllのメンバー
struct V<T>(Vec<T>);
impl<T: Display> PrintAll<T> for V<T> {
fn print_all(self) {
self.0.into_iter().for_each(|x| println!("{}", x));
}
}
例えばこのように任意の実装が出来るからprint_all()はIteratorのメンバーではなくあくまでもPrintAllのメンバー
struct V<T>(Vec<T>);
impl<T: Display> PrintAll<T> for V<T> {
fn print_all(self) {
self.0.into_iter().for_each(|x| println!("{}", x));
}
}
203デフォルトの名無しさん
2021/11/28(日) 00:30:34.72ID:Fw4ypgsa 重要なのはフリー関数の定義じゃなくてパイプライン演算子の適用範囲だぞ
204デフォルトの名無しさん
2021/11/28(日) 00:54:44.73ID:j8Nrs0jp >>201
長くて斜め読みしかしていないがもっとわかりやすく示すとこういうことか
まず状態を示すダミーな型を作っておく
trait State {}
impl State for ToDo {}
impl State for Done {}
#[derive(Debug)]
struct ToDo;
#[derive(Debug)]
struct Done;
次にビルダーの構造体にダミーな型も収容する (サイズはゼロ)
type PD<T> = std::marker::PhantomData<T>;
#[derive(Debug)]
struct Builder<SetA: State, SetB: State> {
a: i32,
b: i32,
_a: PD<SetA>,
_b: PD<SetB>,
}
つまり変数aがセットされたか否かの状態をダミーな_aの型で示す
(つづく)
長くて斜め読みしかしていないがもっとわかりやすく示すとこういうことか
まず状態を示すダミーな型を作っておく
trait State {}
impl State for ToDo {}
impl State for Done {}
#[derive(Debug)]
struct ToDo;
#[derive(Debug)]
struct Done;
次にビルダーの構造体にダミーな型も収容する (サイズはゼロ)
type PD<T> = std::marker::PhantomData<T>;
#[derive(Debug)]
struct Builder<SetA: State, SetB: State> {
a: i32,
b: i32,
_a: PD<SetA>,
_b: PD<SetB>,
}
つまり変数aがセットされたか否かの状態をダミーな_aの型で示す
(つづく)
205デフォルトの名無しさん
2021/11/28(日) 00:58:02.64ID:j8Nrs0jp >>204の続き
初期値ToDoで開始してセットされたらDoneに変える
impl<SetA: State, SetB: State> Builder<SetA, SetB> {
fn new() -> Builder<ToDo, ToDo> {
Builder { a: 0, b: 0, _a: PD {}, _b: PD {}, }
}
fn set_a(self, a: i32) -> Builder<Done, SetB> {
Builder { a, b: self.b, _a: PD {}, _b: PD {}, }
}
fn set_b(self, b: i32) -> Builder<SetA, Done> {
Builder { a: self.a, b, _a: PD {}, _b: PD {}, }
}
}
全部がDoneになった時だけ実行可能にしておく
impl Builder<Done, Done> {
fn execute(&self) {
println!("OK: {:?}", self);
}
}
最初の呼び出しをわかりやすく用
fn new_builder() -> Builder<ToDo, ToDo> {
Builder::<ToDo, ToDo>::new()
}
あとは両方がセットされると実行できる
fn main() {
new_builder().set_a(123).set_b(456).execute();
}
片方でもセットを忘れるとコンパイル時にexecute()が解決できず失敗する
自分でこのコードを毎回間違えずに書くのは面倒なのでマクロ化されるなら採用
初期値ToDoで開始してセットされたらDoneに変える
impl<SetA: State, SetB: State> Builder<SetA, SetB> {
fn new() -> Builder<ToDo, ToDo> {
Builder { a: 0, b: 0, _a: PD {}, _b: PD {}, }
}
fn set_a(self, a: i32) -> Builder<Done, SetB> {
Builder { a, b: self.b, _a: PD {}, _b: PD {}, }
}
fn set_b(self, b: i32) -> Builder<SetA, Done> {
Builder { a: self.a, b, _a: PD {}, _b: PD {}, }
}
}
全部がDoneになった時だけ実行可能にしておく
impl Builder<Done, Done> {
fn execute(&self) {
println!("OK: {:?}", self);
}
}
最初の呼び出しをわかりやすく用
fn new_builder() -> Builder<ToDo, ToDo> {
Builder::<ToDo, ToDo>::new()
}
あとは両方がセットされると実行できる
fn main() {
new_builder().set_a(123).set_b(456).execute();
}
片方でもセットを忘れるとコンパイル時にexecute()が解決できず失敗する
自分でこのコードを毎回間違えずに書くのは面倒なのでマクロ化されるなら採用
206デフォルトの名無しさん
2021/11/28(日) 01:06:31.53ID:eXqoW6w6 またチラ裏コードの垂れ流し
いい加減やめてほしい
いい加減やめてほしい
207デフォルトの名無しさん
2021/11/28(日) 02:33:07.17ID:ZOlCZyFx208デフォルトの名無しさん
2021/11/28(日) 02:38:47.39ID:D4pWSHhU 自己満足コード見せられても困るよな
209デフォルトの名無しさん
2021/11/28(日) 02:48:11.47ID:Fw4ypgsa config部分が静的に決まってるならいいけど
UIやコマンドラインから動的にconfigしたい場合Builder traitを用意してtrait objectとして持ち回して
.execute()するためにdowncastする必要が……とかで二度手間になりそう
UIやコマンドラインから動的にconfigしたい場合Builder traitを用意してtrait objectとして持ち回して
.execute()するためにdowncastする必要が……とかで二度手間になりそう
210デフォルトの名無しさん
2021/11/28(日) 02:53:52.09ID:ghhRE59c >>201のコードがいいと感じる感性が理解できないよ
211デフォルトの名無しさん
2021/11/28(日) 10:39:31.01ID:XbegH2kB >>201
難しい話をすると
ビルダはディレクタに対して抽象化されており
一個のディレクタが複数のビルダをケアできることを考えると
必須パラメータというのをビルダ実装ごとに準備するなら
ビルダというインタフェースがディレクタに対して実質破綻してると思う
でも
ビルダインタフェースが正しい呼び出し順を想定してたりするのをアリとするなら
必須パラメータも同じように勝手に想定しておいて
使う側にはドキュメントなりなんなりで勝手に指示だしとけば十分とも思う
そんで
呼び出し順や必須か否かに想定を置きたくない
呼び出し側に完全な自由度を与えたビルダインタフェースを提供したいなら
インタフェース Fooビルダ {Fooビルダ a(); Fooビルダ b();}
クラス 実際のビルダ implements Fooビルダ {
Foo(必須な何か x) {略} // コンストラクタで与えるとか
Fooビルダ 必須なc() {略} /* 実際のビルダ固有のメソッドとして与えて
new 実際のビルダ().必須なc().a() などと呼ぶか
Fooビルダ a() {略}
Fooビルダ b() {略}
Foo create() {略}
}
のようにして、ビルダインタフェース側だけはクリーンに守っておけばスッキリかも?
元のURLにあるように何が必須かをパラメータ化したいという欲求は解消してないのは認める
難しい話をすると
ビルダはディレクタに対して抽象化されており
一個のディレクタが複数のビルダをケアできることを考えると
必須パラメータというのをビルダ実装ごとに準備するなら
ビルダというインタフェースがディレクタに対して実質破綻してると思う
でも
ビルダインタフェースが正しい呼び出し順を想定してたりするのをアリとするなら
必須パラメータも同じように勝手に想定しておいて
使う側にはドキュメントなりなんなりで勝手に指示だしとけば十分とも思う
そんで
呼び出し順や必須か否かに想定を置きたくない
呼び出し側に完全な自由度を与えたビルダインタフェースを提供したいなら
インタフェース Fooビルダ {Fooビルダ a(); Fooビルダ b();}
クラス 実際のビルダ implements Fooビルダ {
Foo(必須な何か x) {略} // コンストラクタで与えるとか
Fooビルダ 必須なc() {略} /* 実際のビルダ固有のメソッドとして与えて
new 実際のビルダ().必須なc().a() などと呼ぶか
Fooビルダ a() {略}
Fooビルダ b() {略}
Foo create() {略}
}
のようにして、ビルダインタフェース側だけはクリーンに守っておけばスッキリかも?
元のURLにあるように何が必須かをパラメータ化したいという欲求は解消してないのは認める
212デフォルトの名無しさん
2021/11/28(日) 11:48:41.93ID:sDAG0wCq インタフェースとかクラスとか意味不明すぎ
213デフォルトの名無しさん
2021/11/28(日) 23:35:20.49ID:Fzo1fdIE ここまで意味不明な文章書けるのって逆に凄いよ
このレベルは久々に見たわ
このレベルは久々に見たわ
214デフォルトの名無しさん
2021/11/29(月) 01:53:08.06ID:zo5XubVi Javaコードの識別子の部分を日本語で書いて
GoFのオリジナルのBuilderパターンを説明しただけっぽい
なんでRustスレでそんな話をしたのかだけは完全に謎だが……
GoFのオリジナルのBuilderパターンを説明しただけっぽい
なんでRustスレでそんな話をしたのかだけは完全に謎だが……
215デフォルトの名無しさん
2021/11/29(月) 02:06:35.83ID:27e/xIh/ 普通のBuilderであまり困ったことないからなあ
操作によって遷移していく状態があって、状態ごとに可能な操作が違う(呼び出せるメソッドが違う)とかなら意味あると思う(Socketのbind->accept->read/writeみたいな)
ただこういうものはもはやBuilderと呼ぶべきものではないと思う
操作によって遷移していく状態があって、状態ごとに可能な操作が違う(呼び出せるメソッドが違う)とかなら意味あると思う(Socketのbind->accept->read/writeみたいな)
ただこういうものはもはやBuilderと呼ぶべきものではないと思う
216デフォルトの名無しさん
2021/11/29(月) 09:45:31.17ID:3xWgo/Oc それはStateパターンでしょ
217デフォルトの名無しさん
2021/11/29(月) 15:25:28.77ID:aqqw7fQi https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ebfd22dd62614e127bb3dbf0e57e5651
sもmutにしてDerefMutもimplしてるのになんでgの方は通らないんでしょうか?
sもmutにしてDerefMutもimplしてるのになんでgの方は通らないんでしょうか?
218デフォルトの名無しさん
2021/11/29(月) 16:49:12.44ID:4MgUQE5v >>217
もっと単純に let z: *mut i8 = *s; も通らないので
これはDerefMutの条件であるmutable contextを満たしてないのではないか
そしてもちろん let z: &mut i8 = *s; は通るし **s = 88; も通るからDerefMut自体は機能している
もっと単純に let z: *mut i8 = *s; も通らないので
これはDerefMutの条件であるmutable contextを満たしてないのではないか
そしてもちろん let z: &mut i8 = *s; は通るし **s = 88; も通るからDerefMut自体は機能している
219デフォルトの名無しさん
2021/11/29(月) 18:03:30.09ID:3r4jR24z PR出てるけどどうなるかわからない
https://github.com/rust-lang/rust/pull/86647
現状は
let s = &mut *s;
g(*s);
するか
g(&mut **s);
するか
https://github.com/rust-lang/rust/pull/86647
現状は
let s = &mut *s;
g(*s);
するか
g(&mut **s);
するか
220デフォルトの名無しさん
2021/11/29(月) 18:58:43.82ID:Y4F1AeLY221デフォルトの名無しさん
2021/11/30(火) 18:31:42.77ID:8WvE/rry ifの閉じカッコにセミコロンが必要となる条件を教えてください
以下のプログラムはそれが足りないと指摘されてコンパイルエラーとなり
セミコロンを付けると通って動作するのですがどういう原理なのでしょうか?
fn main() {
for line in BufReader::new(io::stdin()).lines() {
let line = line.unwrap();
if let [first, second, rest] = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>()[..] {
println!("{}:{}:{}", first, second, rest);
}
}
}
以下のプログラムはそれが足りないと指摘されてコンパイルエラーとなり
セミコロンを付けると通って動作するのですがどういう原理なのでしょうか?
fn main() {
for line in BufReader::new(io::stdin()).lines() {
let line = line.unwrap();
if let [first, second, rest] = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>()[..] {
println!("{}:{}:{}", first, second, rest);
}
}
}
222デフォルトの名無しさん
2021/11/30(火) 18:58:54.86ID:ZW4IpnTF 戻り値?
223デフォルトの名無しさん
2021/11/30(火) 20:27:35.13ID:s7fhQ2Tk ブロック式最後の式の値は、ブロック式の値として返るので drop されるタイミングがブロックの末尾よりも後の箇所になるということかな
for のブロックは値を返さないけど、ブロック式と同じ扱いをされているっぽい
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b5639623c9a0dff8426f1d38b7123fdc
for のブロックは値を返さないけど、ブロック式と同じ扱いをされているっぽい
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b5639623c9a0dff8426f1d38b7123fdc
224デフォルトの名無しさん
2021/11/30(火) 21:12:32.45ID:8WvE/rry225デフォルトの名無しさん
2021/11/30(火) 21:32:53.10ID:hx6pGpzB help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
↑エラーメッセージに理由書いてるよ
↑エラーメッセージに理由書いてるよ
226デフォルトの名無しさん
2021/11/30(火) 21:55:20.40ID:8WvE/rry >>225
そのエラーメッセージでは理由になっていないのではないでしょうか?
例えば(for文を使わない)>>223の以下の部分を
if let [_first, _second, _rest] = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>()[..] {}
このように2行へ書き換えても同じくセミコロンを付けろエラーとなりますが
let x = line.splitn(3, ' ');
if let [_first, _second, _rest] = x.collect::<ArrayVec<_, 3>>()[..] {}
このように2行へ書き換えるとコンパイルが通ります
let x = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>();
if let [_first, _second, _rest] = x[..] {}
この差をどう見るのか教えていただけますでしょうか
そのエラーメッセージでは理由になっていないのではないでしょうか?
例えば(for文を使わない)>>223の以下の部分を
if let [_first, _second, _rest] = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>()[..] {}
このように2行へ書き換えても同じくセミコロンを付けろエラーとなりますが
let x = line.splitn(3, ' ');
if let [_first, _second, _rest] = x.collect::<ArrayVec<_, 3>>()[..] {}
このように2行へ書き換えるとコンパイルが通ります
let x = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>();
if let [_first, _second, _rest] = x[..] {}
この差をどう見るのか教えていただけますでしょうか
227デフォルトの名無しさん
2021/11/30(火) 22:02:05.25ID:s7fhQ2Tk >>224
・lineの寿命はif-let式の寿命と一致する
・ブロックの最後の文の寿命はブロックを囲む文の寿命と一致する
という仕様になっていると思われる
型は関係なくてブロック内の最後の式か否かが重要
・lineの寿命はif-let式の寿命と一致する
・ブロックの最後の文の寿命はブロックを囲む文の寿命と一致する
という仕様になっていると思われる
型は関係なくてブロック内の最後の式か否かが重要
228デフォルトの名無しさん
2021/11/30(火) 22:26:55.08ID:hx6pGpzB >>226
>このように2行へ書き換えるとコンパイルが通ります
>let x = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>();
line.splitnでborrowしたものを使ってるtemporaryは
let xで受けたタイミングでtemporaryじゃなくなる
(エラーメッセージにあるdropped soonerの状態になってる)
if式がブロックの最後の式でそのif式の一部がborrowを使ってるtemporary
セミコロンがないとtemporaryが解放される前にローカル変数のlineが解放されるからライフタイムのエラー
そのうち修正されるかもしれないけど今はそういう動きってこと
>このように2行へ書き換えるとコンパイルが通ります
>let x = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>();
line.splitnでborrowしたものを使ってるtemporaryは
let xで受けたタイミングでtemporaryじゃなくなる
(エラーメッセージにあるdropped soonerの状態になってる)
if式がブロックの最後の式でそのif式の一部がborrowを使ってるtemporary
セミコロンがないとtemporaryが解放される前にローカル変数のlineが解放されるからライフタイムのエラー
そのうち修正されるかもしれないけど今はそういう動きってこと
229デフォルトの名無しさん
2021/11/30(火) 22:31:28.50ID:hx6pGpzB >>226
>let x = line.splitn(3, ' ');
>if let [_first, _second, _rest] = x.collect::<ArrayVec<_, 3>>()[..] {}
>let x = line.splitn(3, ' ');
>if let [_first, _second, _rest] = x.collect::<ArrayVec<_, 3>>()[..] {}
230デフォルトの名無しさん
2021/11/30(火) 22:35:06.87ID:hx6pGpzB すまん、投稿ミス。
値を返したいときはセミコロンを追加するだけじゃだめだから
一旦変数で受けてからその変数をブロックの最後に書く
値を返したいときはセミコロンを追加するだけじゃだめだから
一旦変数で受けてからその変数をブロックの最後に書く
231デフォルトの名無しさん
2021/11/30(火) 22:39:09.24ID:8WvE/rry ふむむ
lineがヒープにあると以下の2行だけでセミコロン付けろエラーになりますね
let line = String::from("A B C D E");
if let [_first, _second, _rest] = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>()[..] {}
このif let文を例えば以下のように変えるとセミコロンを付けなくても通るのはどうしてでしょう?
if let Some(_s) = line.get(3..6) {}
lineがヒープにあると以下の2行だけでセミコロン付けろエラーになりますね
let line = String::from("A B C D E");
if let [_first, _second, _rest] = line.splitn(3, ' ').collect::<ArrayVec<_, 3>>()[..] {}
このif let文を例えば以下のように変えるとセミコロンを付けなくても通るのはどうしてでしょう?
if let Some(_s) = line.get(3..6) {}
232デフォルトの名無しさん
2021/11/30(火) 22:41:34.40ID:rIKeeiBO なんでセミコロン付けると一時オブジェクトの寿命変わるんだって思ったけどそういえばC++にもそんな仕様あったな……
完全式じゃなくて戻り値に使うから破棄されないってことか
完全式じゃなくて戻り値に使うから破棄されないってことか
233デフォルトの名無しさん
2021/11/30(火) 23:55:05.80ID:Y6JwF3m3 >>230
ブロックの最後で返す値は変数に入れなくても複雑な式でも大丈夫ですよ
ブロックの最後で返す値は変数に入れなくても複雑な式でも大丈夫ですよ
234デフォルトの名無しさん
2021/12/01(水) 12:41:12.28ID:KNT1MQhQ なんでBufReadトレイトはあるのにBufWriteトレイトは無いんですか?
235デフォルトの名無しさん
2021/12/01(水) 13:25:08.66ID:2cjkBPbo >>231
詳しく知りたければまずはここ↓だけど
https://doc.rust-lang.org/reference/destructors.html
言語自体をいじりたいわけじゃなければ
あんまり深追いしても役に立たないよ
詳しく知りたければまずはここ↓だけど
https://doc.rust-lang.org/reference/destructors.html
言語自体をいじりたいわけじゃなければ
あんまり深追いしても役に立たないよ
236デフォルトの名無しさん
2021/12/01(水) 16:06:22.55ID:oI4zTDt2237デフォルトの名無しさん
2021/12/01(水) 21:58:24.00ID:QwFnQ8Qa flushしなけりゃ下のレイヤのどこかで勝手にバッファリングされることがほとんどだから用意する意味がないんだろな。
238デフォルトの名無しさん
2021/12/01(水) 23:34:44.63ID:hYYowF9a >>237
いやBufWriteトレイトが存在しないだけであってBufWriterはちゃんとある
そしてBufWriterがバッファリングする最後の要
誰かが勝手にバッファリングしてくれることはない
例えば何行もファイルに書き込む時にBufWriter使わずに各行毎にwriteしてたら遅くなる
いやBufWriteトレイトが存在しないだけであってBufWriterはちゃんとある
そしてBufWriterがバッファリングする最後の要
誰かが勝手にバッファリングしてくれることはない
例えば何行もファイルに書き込む時にBufWriter使わずに各行毎にwriteしてたら遅くなる
239デフォルトの名無しさん
2021/12/03(金) 14:04:46.92ID:xjf4hyRh https://crates.io/crates/rust-script
とか
https://crates.io/crates/runner
みたいなの使ってる人おる?
これ使うくらいならLL使うとは思うが
とか
https://crates.io/crates/runner
みたいなの使ってる人おる?
これ使うくらいならLL使うとは思うが
240デフォルトの名無しさん
2021/12/03(金) 14:45:17.46ID:RidNMi7I REPL的にコードスニペットの実行確認するために使ったりはできるのかな
今はplaygroundで事足りているが
今はplaygroundで事足りているが
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 台湾有事での集団的自衛権行使に「賛成」が48.8%、「反対」が44.2% ★4 [♪♪♪★]
- 高市早苗首相、独自貫いた1カ月 会食ゼロ、議員宿舎で勉強漬け「飲んでる暇があれば、政策を練り、資料を読みたい」 [Hitzeschleier★]
- 【MLB】大谷翔平、山本由伸、佐々木朗希WBC出場辞退が確実に! トランプ大統領「ロス五輪最優先」指令 どうなる侍ジャパン [牛丼★]
- 岐阜発激安スーパー「バロー」横浜にオープン! [おっさん友の会★]
- 【英FT】国土の大部分を日本の残忍な占領下におかれたという苦しみの記憶を今なお抱え続けている中国 [1ゲットロボ★]
- 中国の渡航自粛、影響は限定的 日本人客が来店しやすく [♪♪♪★]
- 高市早苗「G20サミット、なめられない服を選びました。外交交渉でマウント取れる服買わないとなぁ」大炎上★3 [165981677]
- 【んな専🏡】ルーナイトとたこ焼きパーティするのらぁ(・o・🍬)【ホロライブ▶】
- 有識者「高市総理は中国に切れるカードが3枚あります。その中で1番強力なのが半導体製造装置の輸出禁止」 [931948549]
- 「知名度:S」「面白さ:C」←こういうアニメってある?
- 【悲報】高市早苗内閣自民党支持率、30.7%にwwwwwwwwwwwww [339712612]
- 中国、高市早苗を国連に提訴。「国際社会に問う」 [271912485]
