Rust part8

■ このスレッドは過去ログ倉庫に格納されています
2020/01/24(金) 11:47:52.41ID:9oO1hUHl
Mozilla発のRust言語のスレ

公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust

Web上の実行環境
https://play.rust-lang.org

前スレ
Rust Part7
http://mevius.5ch.net/test/read.cgi/tech/1563114707/
2020/05/03(日) 14:40:33.37ID:CQw0w+cb
>>488
enumで紐つけても結局hogeでmatch使う事になる。
Fnで返すと所謂if文と関数ポインタどっちが早い?的な事になって
最適化するとif文のが早くなる。つまりループの中でMatchしとけば良い。
2020/05/03(日) 21:48:29.60ID:zX3s2fU5
rustのenumはsum typeだからjitがあればmegamorphicでもtracingじゃなくてもjit効いて
インラインキャッシュも必要ないからそのままインライン展開出来るんだが、この辺がAOTの限界だな。
まあ、分岐予測外れるような呼び出しなら初めからvtable使うだろう。

Rust/WinRT見てc++と違っていきなりマクロ出てくるからMFCの悪夢が蘇った。
2020/05/03(日) 22:46:23.02ID:zpY+Khfl
>>492
ローカルにあるcrateとrustのソースをgrepしてみたがほとんど使われてないね

シグニチャに書くことで可読性が高まるケースであれば使えばいいと思うけど
そうじゃなければ一旦受けてから関数内で分割したほうがよさそう
496デフォルトの名無しさん
垢版 |
2020/05/04(月) 11:52:28.65ID:sauq4xLT
レンジ自体にマッチしたいんだけど書きかたって今はない?
match 1..3 {
2..3 => println!("2..3"),
1...3 => println!("matched!"),
_ => println!("_"),
}
2020/05/04(月) 12:22:11.14ID:au6sJ5VU
>>496
use std::ops::Range;

match 1..3 {
Range{start: 2, end: 3} => println!("2..3"),
Range{start: 1, end: 3} => println!("matched!"),
_ => println!("_"),
}
498デフォルトの名無しさん
垢版 |
2020/05/05(火) 02:10:07.89ID:em9v0/Ay
>>497
ありがとう。
でもなんで
match 1 {
1...2 => println!("matched!"),
_ => todo!(),
}
こっちのマッチは ... で一個点々多く使わないといけなくなったの?
Range{start: 2, end: 3}をつかうなら1...2じゃなくて1..2でもよかったんじゃ
2020/05/05(火) 03:39:54.86ID:ZuBK36Gv
...ってまだ使えるのか。..=に置き換えられたのかと
2020/05/05(火) 09:01:40.68ID:uTsiWylk
>>498
matchのarmでrangeを使うケースはほぼ100%inclusive rangeなので
half openのexclusive rangeとは区別して利便性を上げつつ
不用意なバグをコンパイル時に弾けるようにしたのが理由だと思うよ

>Range{start: 2, end: 3}をつかうなら1...2じゃなくて1..2でもよかったんじゃ
んん?
そもそも「レンジ自体にマッチしたい」ってどういう用途?
2020/05/06(水) 11:12:57.23ID:exILxtx0
Rust の API についてはメソッドのシグネチャとコメントからドキュメントを生成できるけど、
バイナリクレートにユーザー向けのドキュメントを付けるときの作法とかってあるの?
2020/05/06(水) 22:11:17.73ID:Rwb7Dx/N
i32とかにあるdiv_euclidってどういうときに使うものなの?
2020/05/06(水) 22:52:21.93ID:A+GAumiz
>>502
「負数の剰余」で調べると違いが分かるかと。
504デフォルトの名無しさん
垢版 |
2020/05/07(木) 16:40:36.21ID:82eQknS5
ドキュメントコメントでのassetでのテストとmod testsってどう使い分けたらいいの?

ドキュメントテストすればユニットテスト書かなくていい?
ドキュメントは使用例だけで、assertでのテストって意味なくね?って思ってしまう。無視もできるし
2020/05/07(木) 17:28:34.50ID:k47Mu4KT
>>504
ドキュメントテストはドキュメントであってテストではない。
説明上分かりやすいならassertしてもいいけど、別になくてもいい。
それでもドキュメントテストを通すのは、古いサンプルコードがいつの間にかコンパイル通らなくなっている、というのを防ぐため。
ユニットテストは普通にmod testsで書けばいいよ。
2020/05/07(木) 18:37:23.38ID:ywncHnjy
doit()はclone()が入るとエラーが出るんだけど何で?
TにCloneが必要って出て来るけどTの実体をCloneしないのに必要ないだろJKって感じのエラーなんだが?
これどうしたらいいの?

https://play.rust-lang.org/?version=stable&;mode=debug&edition=2018&gist=31635004c1ad9fd9e5ba0f859f28ceb0
2020/05/07(木) 19:32:09.83ID:ywncHnjy
>>506
derive使うのやめて自分でClone実装したわ
deriveのCloneがおバカということがわかっただけ収穫とするわ
2020/05/07(木) 19:52:47.71ID:ywncHnjy
これdoit()のget()がTに'static必要ってコンパイル失敗すんだけど
Tを直接扱ってないんだからTに'static要らんだろって感じなんだが?
関数ポインタくらい静的に解決できんだろJK
どうしたらいいんだよ
https://play.rust-lang.org/?version=stable&;mode=debug&edition=2018&gist=b69fe063a3cc2fae6f1cc7536007fe8e
509デフォルトの名無しさん
垢版 |
2020/05/07(木) 21:47:17.14ID:82eQknS5
>>505
てことはドキュメントで書いたコードは普通のコンパイルエラー検知しなくてassertのエラーだけ検知するの?
なんかそれはそれでやばくないか
510デフォルトの名無しさん
垢版 |
2020/05/07(木) 21:48:25.25ID:TSVqZJLC
コンパイル通さずにどうやってassertだけ通すんじゃ
2020/05/07(木) 22:52:31.79ID:ufUjH0LD
>>508
doitのTにstaticを指定すればいい。fn <T:'static> doit ....
2020/05/07(木) 23:07:35.28ID:k47Mu4KT
>>509
いやいや、コンパイルエラーは検知したくてassertはどっちでもいいって話。
コンパイルできないサンプルコードを検出したいんだから。
513デフォルトの名無しさん
垢版 |
2020/05/08(金) 15:31:13.15ID:2R+BCvOe
なんで型って大文字始まりなのにi32とかは全部小文字始まりになってんの?
初期のデザインミス?
2020/05/08(金) 15:47:25.70ID:Pb0t26ee
primitiveは小文字で統一したんじゃないの?
2020/05/08(金) 22:20:21.51ID:UFFnLRtI
0u32
みたいにサフィックスとしても使うし
516デフォルトの名無しさん
垢版 |
2020/05/09(土) 06:11:48.26ID:gxFlq1V3
Rustみたいに標準ライブラリは最小に留めてるような言語って他にありますか?

それとコンパイラ内部のCargo.tomlにライブラリのバージョン書けば別に最小に留めなくてもと思うんですが、どうでしょうか?
2020/05/09(土) 10:20:58.87ID:MmeKQuXy
>>516
Lua とか
2020/05/10(日) 04:53:09.49ID:aajKhScH
>>516
どこまでを最小というかによるがC++は似たようなもんじゃないかしら
519デフォルトの名無しさん
垢版 |
2020/05/12(火) 08:44:05.53ID:l1cRSbJI
これってなんで&mut になんの?
n: mut &i32のほうが差分的にも視覚的にもいいと思うけど、どっかに理由とか書かれてないかな?
fn example(n: &mut i32) {
}
let mut r = &10;
example(mut r);
2020/05/12(火) 10:47:54.41ID:yEVh4LKg
>>519
https://stackoverflow.com/questions/29672373/what-is-difference-between-mut-a-t-and-a-mut-t
2020/05/12(火) 11:12:17.10ID:rr7jvTFY
>>519
変数がmutableなのか、immutableなのかと
変数の型がownedなのか、shared referenceなのか、mutable referenceなのかとは別

mutable referenceを表す記号として`&mut`で一塊なのでmut &i32は微妙
n: mut i32みたいに型として意味のないコードを書いて
何が悪いのかわからないってことになりにくい

コンパイラ的にも`&`が先にあったほうが処理が簡単そう
522デフォルトの名無しさん
垢版 |
2020/05/12(火) 17:14:57.85ID:pSulPVQF
なるほど
2020/05/12(火) 17:49:29.28ID:jco3JkFf
>>521
微妙というかmut &i32だとimmutableなi32へのmutableな参照になるから意味が違うのでは?
もとのi32は変更不可だが別の参照を再bindは可能という。
2020/05/12(火) 18:24:06.26ID:rr7jvTFY
>>523
変数のmutabilityと変数の型をごっちゃにしてない?

`let x: &mut i32`と書くところを
`let x: mut &i32`と書くような文法にしたほうがよかったのでは
ってのが>>519の意見
2020/05/12(火) 19:18:36.86ID:j2+Ql/jy
>>524
その場合、今の文法でmut &i32と書くケースはどうすべきなの?
そこだけ変えちゃうと、全体的に整合性が取れなくなるのではないかと思うけど。
2020/05/12(火) 21:20:08.42ID:rr7jvTFY
>>525
今の文法でmut &i32と書くケースは無いよね?

`let x: &mut &i32`って書くべきケースのことなら
`let x: mut &&i32`になるんじゃない?
2020/05/12(火) 21:34:24.99ID:FmqTBss/
>>526
確かに勘違いしてた。今の文法だとmut x: &i32だった。
なので今は
x: &mut i32
mut x: &i32

x: mut &i32
mut x: &i32
にしても別に問題はないのか。なんとなく両者の区別はしにくくなってる気はするけど。
528デフォルトの名無しさん
垢版 |
2020/05/12(火) 21:45:24.39ID:l1cRSbJI
>>521
パース負荷はおいておいて、mut i32ってかいてあったら普通にコンパイルエラーでよくないか?
エラーの親切さはRustの特徴だし。
mut 書いてる時点で参照なのは当然なんだから書き忘れってすぐわかるじゃん
それに語彙的にmutable referenceとも一致して自然だから前から疑問だった

>>526 のパターンとかも今までの書き方だとかなり読みにくいよね
2020/05/12(火) 22:06:14.36ID:rr7jvTFY
本当の理由は知らないけど、その区別しにくくなるってところがポイントだったんじゃないのかな

mut i32はコンパイルエラーだろうけど、今はエラーメッセージ見ても
&mutがあれば型、mutがあれば変数のmutabilityって詳細読まなくてもすぐ分かる

慣れかもしれんが俺は今の文法のほうが読みやすいと感じる
let mut x: &mut &i32
let mut x: mut &&i32

let mut x: &mut &mut i32
let mut x: mut mut &&i32
2020/05/12(火) 22:08:09.55ID:tQMnmew/
tokio使ってる人いる?
2020/05/12(火) 22:36:30.89ID:RlXY9TUm
>>530
使いたくなくてもネットワーク使うcrateがtokioにべったり依存してて
非同期にこだわる意味ないアプリでも使わざるを得なくなるのがRustのダメなとこ
2020/05/13(水) 00:29:51.86ID:HS9NS6av
actix-webでも中で使ってるしtokio単体でも使ってる
533デフォルトの名無しさん
垢版 |
2020/05/13(水) 01:28:10.47ID:IZIPIE/9
非同期に拘らないならstd::net使えばよくない
2020/05/13(水) 14:58:18.04ID:n4QRUOl7
今の主流は tokio か async-std だけど io-uring 対応でまた勢力図に変化が起きたりするのだろうか
2020/05/13(水) 22:46:58.63ID:0Q+bejh+
乗り遅れた。
tokioは使ってないけどデスクトップでnon-blocking file ioが欲しい。ブロックしたら並列の意味がない。

>>531
ランタイムと付いてくるapiで肥大化するのが問題なんだよね。
2020/05/14(木) 04:55:54.76ID:hWqHBFy5
cargo clippyが通ってcargo buildが失敗するケースってある?
2020/05/14(木) 09:41:17.62ID:WpNijTVY
望まぬ非同期は一応 tokio::runtime::current_thread::block_on_all() で回避できるか
それでもビルドが一気に遅くなる
2020/05/14(木) 15:47:47.58ID:yNXnSs4i
>>536
リンクでエラーになる場合とかはある
539デフォルトの名無しさん
垢版 |
2020/05/14(木) 18:17:46.89ID:nGNfHuw+
なるほど
540デフォルトの名無しさん
垢版 |
2020/05/14(木) 21:36:47.59ID:AoVs9mpY
日本のRust界隈で有用なRust関連のツイートしてる人教えて
2020/05/14(木) 23:31:33.96ID:W3KxELdZ
おれおれ
542デフォルトの名無しさん
垢版 |
2020/05/15(金) 09:40:19.45ID:OlE2WbGd
543デフォルトの名無しさん
垢版 |
2020/05/16(土) 07:49:09.76ID:4fgNGNa5
io-uringと今までの非同期処理の違いってなに?
パフォーマンスそれほど変わるもんなの
2020/05/16(土) 22:12:40.61ID:d7M+qUqk
スレチ
545デフォルトの名無しさん
垢版 |
2020/05/18(月) 04:57:51.24ID:z6Kgscbk
返り値に &'static str ってライフタイム指定ないといけないけど、推論だけで解決できない問題があるから書かないといけないの?
Stringからderefで生成した&strでも結局はIO以外で来たStringは'staticでしょ?推論できそうだけど
2020/05/18(月) 23:19:03.18ID:Uv/lNmsL
>>540
てらモス
2020/05/19(火) 03:57:06.17ID:GltHdsbb
IO以外で来たString、つまりコンパイル時に計算しろってことやな!
let mut string = String::from("abcde");
if long_long_time_consume() != 0 { string.insert(0, 'c') }
require_static_str(&string); // require_static_str : &'static str -> ()
というコードが正しいかどうか、実際に長い長ーい計算しないと分からないけどできるならやれってことやな!絶対使わんわ!
2020/05/21(木) 00:27:51.21ID:uKmbRWt0
paizaにRustの問題ないのつら
2020/05/21(木) 13:46:29.84ID:e7acrJyd
競技プログラミングだとアルゴリズムの理解はともかく言語機能の活用は必ずしも身につかないしなぁ……。

Rust のようなプログラミング言語はいかにして抽象化層を構築するか、
いかにしてミスを防ぐか、
そのために必要なのはどんな機能かに意識が割かれたデザインが多いので、
手早くやることが正義の競技プログラミングではマッチしない。

ステップアップには良いかもしれんが、初心者向けには各言語向けの課題が欲しいよね。
550デフォルトの名無しさん
垢版 |
2020/05/21(木) 19:20:37.36ID:y/uWQkFk
enum MyEnum {
Foo,
Bar,
Baz,
}

のようなデータを載せないシンプルなenumで
Clone/CopyやPartialEq/Eqなどを実装しない場合ってどんな意図があったりするの?
2020/05/21(木) 19:32:35.91ID:BBt3dInh
意図もクソも本来の普通のenumだろ
値そのものに特に意味がなくて、複数のオプションを区別するためだけに使う単なる定数
2020/05/21(木) 19:52:52.75ID:Ge5vC94Q
ただのサボりだろ、省略することに意図なんて無い
2020/05/22(金) 00:12:42.63ID:Aykyb680
Rc<Hoge>のHogeの参照を取りたいとき &*rc_hoge とするのと rc_hoge.as_ref() とするのとどっちがおすすめ?
554デフォルトの名無しさん
垢版 |
2020/05/22(金) 01:00:57.91ID:dJNhuRdN
>>551
同意
2020/05/22(金) 09:19:49.56ID:JweU/zGV
>>551
順序に意味はなくていいが、
Copy は出来て欲しーーってワイは思うやで。
556デフォルトの名無しさん
垢版 |
2020/05/22(金) 20:50:02.94ID:ZwFuqcZd
enumだけ勝手にCopyついてるとか嫌すぎて草

>>553
as_ref()
2020/05/22(金) 21:08:41.77ID:4ZqbW+TE
non_exhaustive で pub な enum は勝手に Copy になると意図せぬ破壊的変更を起こしやすくなってしまう
2020/05/22(金) 21:09:50.79ID:4ZqbW+TE
>>553
Hoge が AsRef 実装してるかもしれないから Rc::as_ref か &*
2020/05/22(金) 21:16:35.95ID:/JyTX0fw
最近ずっと弄ってるけどRust難しいのう・・・
560デフォルトの名無しさん
垢版 |
2020/05/23(土) 09:31:16.71ID:Zkam+XNX
C++がそうだからとかの理由はなしで
[[[i32; 3]; 3]; 3]
がなんで
[3; [3; [3; i32]]]
じゃないの?
行列の時かなり読みにくいしさ
2020/05/23(土) 12:43:47.04ID:Ax4YhvgI
なしでと言うかC++erが記法にノイズを持ち込んでるのは明らかなんだが
2020/05/23(土) 15:44:24.84ID:jzsRlJtI
>>560
それって型としては [[[i32]]] なんでしょ?
大きさの情報は後付けというか、
補足的なニュアンスを感じるので後にくるのが自然だと受け入れてる。
実際のところはどういう議論があったのか知らんけど。
563デフォルトの名無しさん
垢版 |
2020/05/23(土) 19:37:35.36ID:Zkam+XNX
>>561
じゃあこの型をRustに持ち込んだのはC++erのMozilla社員ってこと?

>>562
その型はスライスだから全く別。しかも&もないからそんな型ない
2020/05/23(土) 22:35:14.94ID:xQEe6NOh
let x = Box::new(String::from("foo"));
let y = *x;

これyにmoveできるの入門ドキュメントで説明されてなかったから結構驚いた
2020/05/23(土) 23:03:55.77ID:6goyk3s3
>>563
>その型はスライスだから全く別。しかも&もないからそんな型ない
rustのドキュメントも混同しまくってるけど[T]はDSTのarrayで&[T]がDSTのarrayの借用(スライス)だぞ。

>>564
Boxのrustdocに書いてある
2020/05/24(日) 01:52:15.18ID:tkUtJ987
>>565
[[[i32; 3]; 3]] は存在できるが [[[I32]]] は存在できない
配列の要素毎にサイズが可変となってしまう
567562
垢版 |
2020/05/24(日) 09:30:45.62ID:SCWt5xFf
>>566
スライスにとって要素の数の情報は動的なもの (実質的に fat pointer) で
配列にとっての要素の数は型の一部ってこと?
2020/05/24(日) 17:28:53.26ID:tkUtJ987
>>567
そういうこと
もっと言うと [T] の要素数情報は配列自体ではなく配列への参照 (fat pointer) が保持してるから
[T] が単独で存在することはできなくて、
参照経由の &[T] やスマートポインタ経由の Box<[T]>, Rc<[T]> といった形でしか存在できない
569562
垢版 |
2020/05/24(日) 17:59:17.80ID:SCWt5xFf
>>568
そういうことか。
fat pointer を基礎に据えることを除けば
C/C++ のルールとかなり似てるのでわかりやすいな。
(けどそれ故に C/C++ 的な考え方に引きずられてしまう部分もある……。)
2020/05/24(日) 20:09:44.60ID:sglBbUqv
言いたい事は理解できるが
存在できないって言い方は少し引っかかる
2020/05/24(日) 23:17:03.73ID:WFZqWDFu
6月号で特集が組まれてます
初心者の方は是非
2020/05/24(日) 23:36:35.12ID:a0LhMB8x
なにこれどうなってるの?traitでFizzBuzz?
https://github.com/doctorn/trait-eval
573デフォルトの名無しさん
垢版 |
2020/05/25(月) 09:27:38.21ID:Jp/r3UJz
traitのFizzbuzzに付属してるtrait群がいいね。From実装してなくて爪甘いけど
2020/05/25(月) 22:39:28.81ID:MNSExfZQ
>>566
>[[[i32; 3]; 3]] は存在できるが
unsizedだからできない。
というか存在はしてる。rustはリージョンでメモリ管理するからコンパイル時に
リージョンのサイズが分かる必要があるからDSTが第一級じゃないだけ。
スライスにすればそのスライスのサイズはusize*2だからzoneを確保できるだろ。
コンパイル時にポインタのサイズが分かれば良いだけだから

assert_eq!(::std::alloc::Layout::new::<*const [u64]>(), ::std::alloc::Layout::new::<&[u64]>());

は通る。the bookとnomiconよめ。
2020/05/26(火) 01:25:10.52ID:zMnW+xpW
>>540
https://search.yahoo.co.jp/realtime/search?p=Rust
2020/05/26(火) 09:22:21.48ID:yWo2qZ2t
>>574
(要素数と要素サイズがコンパイル時で既知である必要があるarrayの形では)存在できない
と読んでくれ
577デフォルトの名無しさん
垢版 |
2020/05/26(火) 12:44:21.66ID:tQI2iyhC
::stdの指定の仕方ってなんで使うの?stdじゃなくて
自作のmod std作った時にしか被らないぐらいしか利点なさそう。しかもそんな紛らわしい名前で作らないし
2020/05/26(火) 23:26:23.63ID:yWo2qZ2t
他の crate に公開するマクロで使う
2020/05/26(火) 23:27:54.23ID:yWo2qZ2t
std以外のcrateにも使えるから、モジュールとの名前かぶりで使わざるを得ないときもある
testとか
580デフォルトの名無しさん
垢版 |
2020/05/27(水) 10:28:00.44ID:dVIhbWpz
2018の次期バージョンっていくつ?
2020/05/27(水) 11:01:45.48ID:pv32Gf/H
>>580
Prepare for a possible Rust 2021 Edition
https://github.com/rust-lang/rfcs/blob/master/text/2857-roadmap-2020.md
582デフォルトの名無しさん
垢版 |
2020/05/28(木) 08:05:27.45ID:NpbhHX3L
pub enum KansaiPref {
Osaka,
Hyogo,
Kyoto,
}
こういうenumを文字列から生成する時ってnewよりfrom_strで作った方がいいの?

impl KansaiPref {
fn new(s: &str) -> Self {
use Self::*;
match s {
"大阪" => Osaka,
"兵庫" => Hyogo,
"京都" => Kyoto,
_ => unimplemented!(),
}
}

newかfrom_str

impl FromStr for KansaiPref {
type Err = ...;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use Self::*;
match s {
"大阪" => Osaka,
"兵庫" => Hyogo,
"京都" => Kyoto,
_ => unimplemented!(),
}
}
}
2020/05/28(木) 10:15:20.06ID:Xow4Xb3r
>>582
どっちでもいいと思うけど自分ならfrom_str選ぶ
理由はenumをnewするのにResult(かOption)が返されるシグニチャよりも
input.parse::<KansaiPref>()してResultが返されるほうが意図が伝わりやすいから
2020/05/28(木) 12:26:13.92ID:XHarSIwj
>>582
俺は初心者だから意見としてはそれほどあてにならないけど、
from_str を使った方がいいと思う。
new はただの習慣だが FromStr は制約として機能するので、
既存の枠組みの中で便利に機能する可能性がある。
2020/05/28(木) 22:03:56.44ID:85z31x28
多言語展開を考えるとどれも使いたくねえな…と思ってしまう
2020/05/29(金) 07:36:25.48ID:RYu+vFRR
FromStr実装するならちゃんと Err 返してくれ
2020/05/29(金) 16:33:26.54ID:nAKVwuCz
let a : Box<[T; 1000]> = Box::new([Default::default();1000]);

みたいなのってスタックに要素を作ってからヒープにコピーするようになるから効率が悪いし、
Copy を実装してない型だと使えないみたいなんだけど、これって今はどうするのが常套手段なの?

前提条件として変数の型は Box<[T; 1000]> というのは固定ということにして、
unsafe も避けられるものなら避けたい。
2020/05/29(金) 17:24:59.34ID:lyhnjVvq
>>587
vec![Default::default();1000].into_boxed_slice();
589デフォルトの名無しさん
垢版 |
2020/05/29(金) 21:21:26.13ID:tZarZhzR
>>586
標準でString or &str のパース失敗時に返すErrの型とかあんの?
2020/05/30(土) 00:58:42.40ID:wj/8yI7A
vec! と同じような使い勝手の box! があってもよさそうな気がするけど、
そういうクレートがあったりする?
2020/05/30(土) 01:42:01.99ID:tvhETOJ1
#![feature(box_syntax)]
let a: Box<[T; 1000]> = box [Default::default(); 1000];

https://github.com/rust-lang/rust/issues/53827
2020/05/30(土) 01:46:59.27ID:wj/8yI7A
>>591
おおっ、これぞ私が必要としていたもの!
■ このスレッドは過去ログ倉庫に格納されています