Rust part8

■ このスレッドは過去ログ倉庫に格納されています
0292デフォルトの名無しさん
垢版 |
2020/03/26(木) 14:56:26.41ID:RidRralQ
>>291
それは >>267 とちゃんと整合しているな。
Option<T>は、Copy と Cloneの両方が実装されていると言うことで、
ならば、原則論からすればOptionは代入演算子でMove動作「ではなく」Copy動作
だということになる。
0293デフォルトの名無しさん
垢版 |
2020/03/26(木) 15:33:44.04ID:5np4UAxw
>>292
>ならば、原則論からすればOptionは代入演算子でMove動作「ではなく」Copy動作
は?
where T: Copyって書いてるやん
オレオレ原則論書き散らかして荒らすのやめてくれ
0294デフォルトの名無しさん
垢版 |
2020/03/26(木) 17:17:35.74ID:mwwmClxG
c++の代替というけど、rust理解するにはc++でメモリイメージ固めた方が学習速いんじゃねーの?
0296デフォルトの名無しさん
垢版 |
2020/03/26(木) 21:50:13.71ID:HC2i5ubn
ML系列の記法に慣れるとrustがどうしてalgol系列の記法にしたのか納得できなくなる。どんだけカンマ打たせるねん。
少し頑張れば関数の型も推論できると思うんだけど人まかせにしてるのが好きじゃない。せめて、勝手に挿入できるような記法にしとくべきだったと思う
0297デフォルトの名無しさん
垢版 |
2020/03/27(金) 00:25:53.78ID:GUIIkCWN
インスタンスでフィールドアクセスにカンマ使わない場合どんなのがいいの?

推論は関数で境界作りたかったんでしょ
0298デフォルトの名無しさん
垢版 |
2020/03/27(金) 00:33:57.86ID:GUIIkCWN
>>282
日本語のコメントはどう書くだけなのか聞きたかったから特に意図はない例だよ

>>283
完全な例だからあれだけどBoxではない
struct Person {
name: String,
}

impl Person {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string()
}
}
}
0299デフォルトの名無しさん
垢版 |
2020/03/27(金) 00:47:04.38ID:4wGUX1E+
型推論の能力的には関数も全部できるけど、ドキュメント目的であえてしてないはず。
0300デフォルトの名無しさん
垢版 |
2020/03/27(金) 01:16:32.86ID:xxRyEnpG
TypeScriptは戻り値の型を省略できるけど、書かないと訳が分からなくなるので言語的には省略出来てもコーディングルールで強制してるわ
Cみたいに変数宣言含めて型を全部書くのも面倒だけど、行き過ぎた省略もメンテナンス性を損なうと思う
0302デフォルトの名無しさん
垢版 |
2020/03/27(金) 15:34:02.04ID:9RtDMjhb
C/C++に疲れた人が使って幸せになれるのがRustだと思ってたけど
実態は全然違うってことか
0303デフォルトの名無しさん
垢版 |
2020/03/27(金) 17:00:38.31ID:pa89frlH
C++17に疲れた人なら結構幸せになれるんじゃない。
C89に疲れた人だと厳しそうだが…。
0304デフォルトの名無しさん
垢版 |
2020/03/27(金) 18:51:24.66ID:JRwFCn2R
RustのコンパイラソースをCloneしてそれをベースに名前も違うプログラミング言語作るのってライセンス的にどうなの?
rustcの構文解析の部分を変えてからそのrustcも全部その言語に変換したいんだけど
0305デフォルトの名無しさん
垢版 |
2020/03/27(金) 18:57:46.96ID:VaiYZBCN
>>304
そういう考えだから、人を馬鹿にするんだな。
ちょこっといじっただけの癖に全体を自分が造ったみたいな態度をとる。
0306デフォルトの名無しさん
垢版 |
2020/03/27(金) 19:49:39.79ID:oRj/lH5B
>>299 あえてやらないなら、せめてコンパイラが推論した結果を教えてくれよと思う
この処理のこの部分だけ一旦切り出して別の処理にしてみたい、とかやるときにすげー大変

Haskellでも型表記は省略できるけどしない方が良いねって作法がメジャーなのは知ってるけど、型推論でサポートしてくれるからrustよりストレス少ない
ちょいとクロージャを関数として外に出しとこう、とか、ここ切り分けて別パターン用意して比較してみよう、とかやるのが面倒くさい

あ、まずクロージャにして型エラーを起こして教えてもらう、とかやればできるんかな…
0307デフォルトの名無しさん
垢版 |
2020/03/27(金) 19:59:43.89ID:Pf+eY36z
>>306
型を自分で書くのが面倒なときは()とかi32とか適当な型で埋めておいて、エラーメッセージから正しい型を持ってくるというのはありだよ。
(逆に言えば正しいエラーメッセージを出せるということは、関数プロトタイプまでちゃんと型推論できているということでもある)
0308デフォルトの名無しさん
垢版 |
2020/03/27(金) 21:21:00.05ID:aLfv28Wa
関数の型を推論するのを捨ててるから
Deref coercionだったりFrom/Intoだったり中身を書くときに型を省略できるんじゃないの?

owned/shared/mutの違いに加えてlifetimeもあるから
それらも含めて推論することになると現実に使えるレベルになるのかどうか怪しい
少なくとも現時点で注力するようなポイントじゃないと思う
0309デフォルトの名無しさん
垢版 |
2020/03/27(金) 22:30:46.16ID:TRjL1ru9
>>304
ライセンス的にも道義的にもなんの問題もないんで、ぜひ面白言語作ってくれ。
Rust/Cargoの名前やロゴ使うと商標権には引っかかるのでそこだけちゃんと変えてればOK。
0310デフォルトの名無しさん
垢版 |
2020/03/28(土) 02:49:23.51ID:7+pamnWR
>>309
コミットも常に最新を本家からチェリーピックして最新機能とか享受大丈夫?
道理的に叩かれそうじゃない?
0313デフォルトの名無しさん
垢版 |
2020/03/28(土) 20:00:00.22ID:KbJ2BCU2
githubのissueのタグで頭についてるE-easyとかT-compilerみたいな大文字のアルファベットってどういう意味があるの?
0315デフォルトの名無しさん
垢版 |
2020/03/28(土) 21:34:01.64ID:+WXFsbEZ
>>310
ライセンス的には問題ない
道義的にはライセンス踏襲してRustを元にしてるよって書いとけば問題無いと思う
0316デフォルトの名無しさん
垢版 |
2020/03/29(日) 13:50:06.97ID:c6UG4oSX
この引数に&つけるのって
iter.map(|&i| i * 2)
これと同等?
for i in iter {
let i = &i;
}
0317デフォルトの名無しさん
垢版 |
2020/03/29(日) 15:02:02.33ID:sFvWmixp
巨大な学術掲示板群 アルファ・ラボ
ttp://x0000.net

物理学 化学 生物学 数学 天文学 地理地学
IT 電子 工学 言語学 方言 国語 など
0319デフォルトの名無しさん
垢版 |
2020/03/30(月) 03:34:27.53ID:QPHAwv8T
>>318
let i = 1;
let &i = i;
これだとコンパイル通らないよ
0321デフォルトの名無しさん
垢版 |
2020/03/30(月) 03:57:10.09ID:Oymj8mf6
iter.map(|i| i * 2)
と書いた場合、|i| i * 2 の部分は、closure や Lambda expression, lambdas
と呼ばれるものなんだろうけど、|&i| と書く形式はなかなか検索では出てこない。
0323デフォルトの名無しさん
垢版 |
2020/03/30(月) 04:40:37.32ID:Oymj8mf6
>>322
ところで、
let &x = y;
ってどういう意味ですか?

let y:i32 = 5;
let x:&i32 = y;
とは違うんでしょうか?
0325デフォルトの名無しさん
垢版 |
2020/03/30(月) 11:38:27.40ID:/1SwYHDd
>>323
左辺に代入する時にパターンマッチ使ってDestructuringしてる
例えばyが&i32ならxはi32になる

let i = 1;
let &i = i;
これがコンパイル取らないのは
右辺がintegerで左辺がreferenceを要求しててマッチしないから

let i:i32 = 1;
let i = &i;
let &i = i;
let i:() = i;
↑こうやって試せば3行目の&iへの代入でiが&i32じゃなくi32になってるのが分かる
https://play.rust-lang.org/?version=stable&;mode=debug&edition=2018&gist=1d23370e99b388e2205c43e863885315
0327デフォルトの名無しさん
垢版 |
2020/03/30(月) 14:34:27.40ID:yinACqvq
>>326
C で言う void みたいなもんだよ。
あり得ない型を指定してエラーメッセージを出させたら
メッセージに右辺の側の型も表示されるという
型確認のテクニック
0328デフォルトの名無しさん
垢版 |
2020/03/30(月) 15:23:14.22ID:/1SwYHDd
1.38からはstd::any::type_nameがstabilizeされてるので
エラーメッセージやnightly使わずに変数の型をprintして確認できるみたい
(consumeしないようにreferenceで渡すから少し分かりにくいかもだけど)

fn type_of<T>(_: &T) -> &str {
std::any::type_name::<T>()
}

fn main() {
let i = 1;
let i = &i;
let &i = i;
println!("{}", type_of(&i));
}

type_name_of_valってのも追加されてるけど
こっちはまだstabilizeされてない
0329デフォルトの名無しさん
垢版 |
2020/03/30(月) 16:45:46.87ID:Oymj8mf6
>>327
なるほど。貴重なテクニック有難うございます。

>>328
それを使えば構造体(?)や参照型などの lifetime も表示できますでしょうか?

何か lifetimeを確認する方法をご存知の型がいらっしゃればご教授頂ければ幸いです。
0331デフォルトの名無しさん
垢版 |
2020/03/30(月) 18:43:59.32ID:QPHAwv8T
/1SwYHDd氏やるなぁ
こういう細かいことまで知ってる人のRust歴気になる
0332デフォルトの名無しさん
垢版 |
2020/03/31(火) 00:49:28.04ID:bdtzxXSI
さっきオナラしようとしたらウンチが少し出てしまったんだけど
ばれてないからいいよね ごめんね
0335デフォルトの名無しさん
垢版 |
2020/04/01(水) 05:04:17.87ID:2vQ3PjhV
やりたいこと
Optionからの安全な値の取り出しを構文レベルで保証、およびNone時に数行の処理と戻り値を伴う正常の早期returnをしたい

if Some(v) = foo.get() {
安全に取り出せるがネストが嫌すぎる
} else {
位置が遠すぎる
}

let v = if Some(v) = foo.get() {
v        安全取り出しだが冗長すぎて嫌
} else {
}

let v = match foo.get() {
Some(v) => v    安全取り出しだが冗長すぎて嫌
None => { }
}

if foo.is_none() {
構文で保証されずプログラマの注意力次第で嫌すぎる
}
let v = foo.get().unwrap();

let v = foo.get().ok_or_else(||{
は?正常終了つってんだろが?エラー値で返すんじゃねえよバカか?
})?;
0338デフォルトの名無しさん
垢版 |
2020/04/01(水) 09:19:54.63ID:yrAQuZWY
構文を調整したいならマクロじゃない?
let v = safe_get!(v, {
失敗した
return Ok (());
});
みたいな。ベタ書き以外でearly returnしたいならマクロか?演算子みたいにコンパイラサポートがいると思う。
0339デフォルトの名無しさん
垢版 |
2020/04/01(水) 10:13:55.16ID:0Fs3VJge
なんでboolって1byteあるの?
0340デフォルトの名無しさん
垢版 |
2020/04/01(水) 11:20:10.79ID:5VJq6KKK
C は bit field あるのにな
0341デフォルトの名無しさん
垢版 |
2020/04/01(水) 11:25:37.12ID:qjrNWUcZ
>>335
map_or_elseでSomeの時とNoneの時に適用するクロージャを渡せる
でもどうしても1行で書きたいとかchainしたい場合じゃなければ普通にmatchかif-else使うな

fn foo(){
get().map_or_else(|| bar(), |x| baz(x))
}

fn foo(){
match get() {
None => bar(),
Some(x) => baz(x)
}
}

https://play.rust-lang.org/?version=stable&;mode=debug&edition=2018&gist=dd9040426e54f1dfc6e39d07bbd219fb
0344デフォルトの名無しさん
垢版 |
2020/04/01(水) 13:43:58.79ID:npfcBiID
>>343
それはearly returnって言わなくない?
そりゃ結果は同じだけど、元の人は構文的なことを言ってるわけで。
0345デフォルトの名無しさん
垢版 |
2020/04/01(水) 14:12:02.37ID:Wuhu+msT
ネストが嫌なんだから無理でしょ
ネストしないコードを書く人なんだろうけど
0346デフォルトの名無しさん
垢版 |
2020/04/01(水) 17:06:40.66ID:qjrNWUcZ
>>344
なるほど理解した

どうしてもearly returnがしたくてunwrapも嫌なら
if letを2回やるか、is_none+if let Someでもいい気がする
マクロ書いてもidiomaticな形に比べて読みやすくなるかっていうと微妙なので

fn foo(x: &str) -> Result<()>{
let v = safe_get!(get(x), { …; return Ok(()) });
let v = baz(v)?;
qux(v)?
}

fn foo(x: &str) -> Result<()>{
if let Some(v) = get(x) {
let v = baz(v)?;
qux(v)?;
}
Ok(())
}
0347デフォルトの名無しさん
垢版 |
2020/04/01(水) 19:39:22.27ID:2vQ3PjhV
"処理と戻り値"を伴う""正常""の早期returnをしたいといってるだろがErrでラップして返すとかバカか?

こういうSomeから取り出すだけの部分が冗長だから消えてなくなれつってんだよ
is_none()でやるのは構文保証ではなく"プログラマーの注意力"による保証だからクソだつってんだよ

let v = match foo.get() { Some(v) => v, None => {
bar.modify();
baz.modify();
return Ok(bar, baz);
}};

let v = if let Some(v) = foo.get() { v } else {
bar.modify();
baz.modify();
return Ok(bar, baz);
}};
0348デフォルトの名無しさん
垢版 |
2020/04/01(水) 20:41:14.76ID:SX13wyIA
>>347
だからその冗長な部分はマクロで潰せと言ってるんだが。
マクロが嫌なら無理としか言いようがないが。
0352デフォルトの名無しさん
垢版 |
2020/04/01(水) 21:36:47.02ID:qjrNWUcZ
>>347
>"処理と戻り値"を伴う""正常""の早期returnをしたいといってるだろがErrでラップして返すとかバカか?

えっ、 Errでラップして返してる?

まぁそれはいいとしてearly returnだけじゃなく
戻り値の型と取り出した値をどうするかをセットで考えてないから
そうなっちゃうんだと思うよ
0353デフォルトの名無しさん
垢版 |
2020/04/01(水) 22:01:23.20ID:SX13wyIA
RFCざっと見てきたけど、あっちでも
「map_errでいいんじゃ?」「return;できねーよ」ってやってるな。
そんなに難解なリクエストでもないと思うんだが。
0354デフォルトの名無しさん
垢版 |
2020/04/01(水) 22:20:38.50ID:0Fs3VJge
fn check<T>(mut f: impl FnMut(T) -> bool)

fn check<T, F>(mut f: F)
where F: FnMut(T) -> bool
って同意義ですか?
0355デフォルトの名無しさん
垢版 |
2020/04/02(木) 03:46:30.54ID:0zdT1xZ7
>>354
恐らくだけど、前者は必ずその関数を定義する。
後者は、Fがその型の場合にのみその関数を定義する。
0356デフォルトの名無しさん
垢版 |
2020/04/02(木) 03:48:18.19ID:0zdT1xZ7
なお、このような場合の whereは、日本人感覚からすれば、ifと読み替えてもいい。
0357デフォルトの名無しさん
垢版 |
2020/04/02(木) 05:35:03.07ID:zwgg3bUK
前者の場合 check::<T, F>() でコールできるが後者はできない
0358デフォルトの名無しさん
垢版 |
2020/04/02(木) 17:07:56.47ID:SaXsz2/b
前者と後者が逆?
0360デフォルトの名無しさん
垢版 |
2020/04/02(木) 21:53:44.49ID:zwgg3bUK
>>358
逆にだったすまん
0361デフォルトの名無しさん
垢版 |
2020/04/02(木) 23:30:20.89ID:SaXsz2/b
そもそもcheck::<T, F>()じゃ引数渡してないから呼び出せなくない? 試してないけど
0362デフォルトの名無しさん
垢版 |
2020/04/03(金) 00:13:24.70ID:RIPEgpHK
構文で解決すべきところを皆が俺俺マクロで解決して統一感ない状態を生むのが良いと考えるやついるのか?
0363デフォルトの名無しさん
垢版 |
2020/04/03(金) 00:44:31.97ID:11HfTHW1
if foo.is_none() {
シンプルにこれでいいと思うんだが...
これぐらいの細かい挙動で構文拡張しろとかマクロ書けとかなったらC++みたいになっていくのが目に見えるしから嫌だわ
しかもこんな嫌だ嫌だ言ってて質問する立場なのにこんな逆ギレもしてて救いようがない
0364デフォルトの名無しさん
垢版 |
2020/04/03(金) 00:44:38.25ID:8O7qKRUc
現状は335が冗長と言う状態で統一されてるんだからいいんじゃないの。
その冗長さをどうしても許容できない人は(少数派である以上)マクロで解決するしかないし、もし大多数が賛同できる新構文を思い付いたならRFC出せばいい。
0365デフォルトの名無しさん
垢版 |
2020/04/03(金) 14:52:15.88ID:11HfTHW1
test bench_test ... bench: 111,111 ns/iter (+/- 11,111)
ベンチマークの +/- ってどういう意味?
0366デフォルトの名無しさん
垢版 |
2020/04/03(金) 15:47:04.36ID:uTu5qR57
>>363
is_none()は==NULLや==nilと同じ書き忘れのリスクを伴う"プログラマの注意力"を消耗するだけのゴミだろ
0368デフォルトの名無しさん
垢版 |
2020/04/03(金) 19:54:55.15ID:CGYa3yhA
if letやmatchにしないとSomeだったときの処理書けないしょ
0370デフォルトの名無しさん
垢版 |
2020/04/04(土) 00:07:28.35ID:cnL2FB3T
rust実用化に成功したプロジェクトって何があるの?お前らの会社では成功してるの?
0374デフォルトの名無しさん
垢版 |
2020/04/04(土) 08:43:05.69ID:ziV4A0+Z
Utcはフィールドを持たないstructだから
イメージ的にはUtc{}.ymdとしているかんじ
0377デフォルトの名無しさん
垢版 |
2020/04/04(土) 17:26:12.04ID:9lNQDQEm
pub が付いてないものをそんなに簡単に使えたらモジュールの意味がないやろ……。
0378デフォルトの名無しさん
垢版 |
2020/04/04(土) 17:26:43.72ID:9lNQDQEm
そのモジュールをコピペして新しいモジュールを作れば自由に出来るんとちゃう?
0380デフォルトの名無しさん
垢版 |
2020/04/04(土) 20:42:49.37ID:oHbtMe0Y
iteratorを受け取ってSelfを返す。
iteratorは各要素がImageResult<Frame>のもの

Box<dyn …>してるのはコンパイル時にTrait ObjecのSizeが決まるようにするため
(Generics使えば不要)

‘aはiteratorのlifetimeをSelfのlifetimeにするため
0382デフォルトの名無しさん
垢版 |
2020/04/05(日) 10:19:35.11ID:LNp8foc9
>>381
dyn は C++ で言う抽象クラスみたいなもんだよ。
トレイトオブジェクトというのは実際にはそのトレイトを実装している様々な型の可能性があって、
それら全てを格納可能な大きさはわからない。
Box は C/C++ でいうポインタみたいな用途で使われる。
大きさがわからなくてもオブジェクトの場所を指すことは出来る。

「そのトレイトを実装している型ならなんでも」と「そのトレイトを実装している型のいずれか」というのは違う意味で、
ジェネリクスは後者。
言い換えると、実行時にディスパッチされる多相とコンパイル時にディスパッチされる多相ってこと。
コンパイル時に型がわかるのなら大きさもコンパイル時にわかる。
大きさがわかるなら Box を経由しなくていい。

ライフタイムの 'a は Frames の型引数の 'a と同じだから、
new の返り値 (Self) の寿命は iterator の寿命と同じになる。
0383デフォルトの名無しさん
垢版 |
2020/04/05(日) 11:42:45.53ID:/6aVgV0B
Boxと&dynの違いって参照元がヒープかスタックかの違い?
0385デフォルトの名無しさん
垢版 |
2020/04/05(日) 14:35:00.95ID:8bGOOvBY
>>381
大前提として変数や関数の引数や戻り値はコンパイル時にサイズが決まってないといけない

Iterator Traitを実装してる型を引数として受け取りたいからといって
`pub fn new(iterator: Iterator<…>) -> Self` と書くと
Iterator Traitのサイズがコンパイル時にはわからないのでコンパイルエラーになる
`let foo: str;`でエラーになるのと同じ

Box<dyn Trait>か&dyn Traitの形にすれば
Iterator Traitへの参照(=Trait Objectというfatポインタ)になって
受け渡しするサイズが固定されるのでエラーにならない

ジェネリクスを使って
`pub fn new<T: Iterator<…>>(iterator: T) -> Self` と書いた場合は
実際の呼び出しに使われているTの型ごとにコンパイラがバイナリを生成するので
コンパイル時にTのサイズが決まってる (impl Trait使った場合も同じ)

>>382も書いてるように前者は動的ディスパッチ、後者は静的ディスパッチなので
異なる型が混在するコレクションを使いたい時やバイナリサイズを小さくしたい時以外は
ジェネリクスを選ぶほうが一般的
0386デフォルトの名無しさん
垢版 |
2020/04/05(日) 17:53:06.31ID:fOt2g8TG
あーなんとなくわかってっきた
ジェネリクスと同じことがトレイトオブジェクトでも実現できて、その書き方がBox<dyn...>ということか
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況