公式
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を学ぶ際に犯しがちな12の過ち
https://dystroy.org/blog/how-not-to-learn-rust
※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 part13
https://mevius.5ch.net/test/read.cgi/tech/1636247099/
探検
Rust part14
■ このスレッドは過去ログ倉庫に格納されています
2022/02/12(土) 01:24:16.59ID:XYE+Rws6
657デフォルトの名無しさん
2022/04/15(金) 19:50:10.79ID:rQzdCva+ ありがとう!
なんかちょっとズレたエラーメッセージだなと思っても、省略・推論されているなんて夢にも思わなかったから意味がわんなかったぜ!
なんかちょっとズレたエラーメッセージだなと思っても、省略・推論されているなんて夢にも思わなかったから意味がわんなかったぜ!
658デフォルトの名無しさん
2022/04/16(土) 15:01:46.93ID:Tmn9GDW2 Rustって参照をベクターに持てる?
659デフォルトの名無しさん
2022/04/16(土) 15:58:22.55ID:hx1ZC8lU >>658
もてるよ
https://ideone.com/ZMCl2R
fn main() {
let a = 1;
let b = 2;
let v = vec![&a, &b, &a, &b];
println!("{:?}", &v);
}
もてるよ
https://ideone.com/ZMCl2R
fn main() {
let a = 1;
let b = 2;
let v = vec![&a, &b, &a, &b];
println!("{:?}", &v);
}
660デフォルトの名無しさん
2022/04/16(土) 17:14:58.83ID:Tmn9GDW2 >>659
サンクス
サンクス
661デフォルトの名無しさん
2022/04/20(水) 18:37:23.24ID:3eLEi52G Rust 入門者です。
全く実用的な意味はなく練習として符号無し整数を桁ごとに返すイテレータというものを考えていたのですが
同じ制約を重複して書くことになってしまい不格好な気がします。
https://ideone.com/qOmnhW
ベテランが華麗に書いたらどんな風になりますでしょうか。
それとも Rust ではこれで良いものなのでしょうか。
全く実用的な意味はなく練習として符号無し整数を桁ごとに返すイテレータというものを考えていたのですが
同じ制約を重複して書くことになってしまい不格好な気がします。
https://ideone.com/qOmnhW
ベテランが華麗に書いたらどんな風になりますでしょうか。
それとも Rust ではこれで良いものなのでしょうか。
662デフォルトの名無しさん
2022/04/20(水) 19:13:19.89ID:uLqNeO4/ >>661
traitの方の制約はいらないよ
traitの方の制約はいらないよ
663デフォルトの名無しさん
2022/04/20(水) 22:38:14.51ID:3eLEi52G >>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 の段階でエラーであって然るべきだという判断が
重複する制約を書いた意図です。
メソッドがイテレータを返すなんていうのはよくあることだと思うので、
いちいち重複したことを書かかなくて済むような何かがあるんじゃないか……という想像から質問した次第です。
ありがとうございます。
たしかにこのコードではトレイト Digits にスーパートレイトを付ける必要はないですね。
想定を後出しにして誠に申し訳ないのですが、これはライブラリ (クレート) としてまとめようとしているつもりでした。
ここに書かれていない未知の型にトレイト Digits を実装することがあり得るという意味です。
問題になるのは、 Digits のスーパートレイトを消してしまうとどんな型でも Digits の実装自体は出来てしまうということです。
// ↓ Digits にスーパートレイトを付けなければこう書くこと自体は出来てしまう。 この段階でエラーになって欲しい。
struct Foo {}
impl Digits for Foo {}
そしてメソッド digits を呼出すところでエラーになります。
let bar = Foo {};
for x in bar.digits() { // ← ここでエラーになる
println!("{}", x);
}
逆に言えば digits を呼出さなければエラーになりません。
どうせ使えないことがわかっているならトレイトの impl の段階でエラーであって然るべきだという判断が
重複する制約を書いた意図です。
メソッドがイテレータを返すなんていうのはよくあることだと思うので、
いちいち重複したことを書かかなくて済むような何かがあるんじゃないか……という想像から質問した次第です。
664デフォルトの名無しさん
2022/04/20(水) 23:00:49.13ID:uLqNeO4/ >>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,
としても良いかもね
そういう前提ならばこんな感じで 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,
としても良いかもね
665デフォルトの名無しさん
2022/04/21(木) 00:02:58.32ID:9+GFB0OX666デフォルトの名無しさん
2022/04/21(木) 13:57:26.69ID:Ast3pmta 数値にメソッドを生やすメリットが思いつかないからこれだけでいいんじゃない?
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}");
}
}
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}");
}
}
667デフォルトの名無しさん
2022/04/21(木) 14:14:33.93ID:Q5xBjMYc 実用上は関数で十分だろうけど、Rustって整数のプリミティブ型にもたくさんメソッドあるし、
メソッドを生やすのが流儀なのかな、って俺も思ってたけどどうなんやろ?
メソッドを生やすのが流儀なのかな、って俺も思ってたけどどうなんやろ?
669デフォルトの名無しさん
2022/04/21(木) 22:20:02.87ID:NWAfliAT >>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}");
}
}
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デフォルトの名無しさん
2022/04/22(金) 09:19:03.80ID:oJU3aoBf rfc2071かな
671デフォルトの名無しさん
2022/04/22(金) 09:42:40.77ID:sg+qNIV4 >>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);
こんな記述もできるようになるわけね
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);
672デフォルトの名無しさん
2022/04/22(金) 11:24:39.82ID:QUxpZq2Z673デフォルトの名無しさん
2022/04/22(金) 11:28:58.18ID:xFM+XidE >>672
具体的にはどんなコードになるのですか?
具体的にはどんなコードになるのですか?
674デフォルトの名無しさん
2022/04/22(金) 11:29:43.00ID:QUxpZq2Z >>669
>>672 の意図はこんな感じ。返り値も associated type にして実装に委ねられるようにした。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1dfdb310cd07023a69acca6cbba434ed
>>672 の意図はこんな感じ。返り値も associated type にして実装に委ねられるようにした。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1dfdb310cd07023a69acca6cbba434ed
675デフォルトの名無しさん
2022/04/22(金) 12:09:33.52ID:L/Q81szU >>674
where制約宣言の場所をメソッドfnからimplへ移動させることで結果的にtrait側で制約する必要がなくなるわけか
where制約宣言の場所をメソッドfnからimplへ移動させることで結果的にtrait側で制約する必要がなくなるわけか
676661
2022/04/22(金) 13:12:07.76ID:rYail8LQ >>674
元々の想定では符号付きの場合を型の制約で排除したいと考えていました。
トレイトが実装されているかどうかだけでは必要な性質を満たしているかどうか判定しきれないと考えて
個別に実装する必要があるという判断をした次第です。
個々に人が判断するのではなく制約で包括的に判定するとしたら std::ops::Neg を実装して「いない」という条件を付ける
必要が出てくるかと思いますが、今の Rust だとそういう制約は付けられないですよね?
元々の想定では符号付きの場合を型の制約で排除したいと考えていました。
トレイトが実装されているかどうかだけでは必要な性質を満たしているかどうか判定しきれないと考えて
個別に実装する必要があるという判断をした次第です。
個々に人が判断するのではなく制約で包括的に判定するとしたら std::ops::Neg を実装して「いない」という条件を付ける
必要が出てくるかと思いますが、今の Rust だとそういう制約は付けられないですよね?
677デフォルトの名無しさん
2022/04/22(金) 14:11:21.60ID:RekYcGSo678デフォルトの名無しさん
2022/04/24(日) 14:55:18.07ID:SDl1bpLd >>675
trait宣言でtrait境界制約しないメリットは他にもある
例えば文字列(例 "57261")に対するdigits()をimplできるようになってこの場合は別のtrait境界をimpl側で書くことになる
ただし別問題として現状ではまだ安定化していない2つの機能サポート待ち
1つ目はimpl Traitのspecializationでfor Tが既にあるところへfor Stringやfor &strできるようにするため
もう1つはGATs (general associated types)でイテレータで参照返しできるようにするため
trait宣言でtrait境界制約しないメリットは他にもある
例えば文字列(例 "57261")に対するdigits()をimplできるようになってこの場合は別のtrait境界をimpl側で書くことになる
ただし別問題として現状ではまだ安定化していない2つの機能サポート待ち
1つ目はimpl Traitのspecializationでfor Tが既にあるところへfor Stringやfor &strできるようにするため
もう1つはGATs (general associated types)でイテレータで参照返しできるようにするため
679デフォルトの名無しさん
2022/04/25(月) 18:30:29.96ID:5VI7zZaU 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 };
}
こういう書き方をすると 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 };
}
680デフォルトの名無しさん
2022/04/25(月) 19:55:08.99ID:6A0Kp8FF >>679
配列は長さ固定
長さが異なれば別の型となる
マッチングは全て同じ型でなければならない
つまり長さ1の配列パターンがあるならば全て長さ1の配列
つまり配列としてマッチングする必要がない
実際には長い配列で先頭だけマッチングしているとしてもfoo[0].as_str()でよい
おそらく例として簡略化して書いたのだろうがもう少し具体化した方がアドバイスを受けやすい
配列は長さ固定
長さが異なれば別の型となる
マッチングは全て同じ型でなければならない
つまり長さ1の配列パターンがあるならば全て長さ1の配列
つまり配列としてマッチングする必要がない
実際には長い配列で先頭だけマッチングしているとしてもfoo[0].as_str()でよい
おそらく例として簡略化して書いたのだろうがもう少し具体化した方がアドバイスを受けやすい
681デフォルトの名無しさん
2022/04/25(月) 23:28:44.10ID:QcJ2t2WS 配列を使わずにスライスを使えば可変長マッチングができる
682デフォルトの名無しさん
2022/04/26(火) 02:22:33.26ID:9/mVSM+b 問題はそこじゃなくて &[String] をパターンマッチする方法がないってことだよね
683デフォルトの名無しさん
2022/04/26(火) 02:43:40.86ID:uT+rLtYK Stringのままだと、文字列のマッチはガードでやるしかなそうだし、
その場合なら &str にしてからマッチしたほうが良さそうだね
その場合なら &str にしてからマッチしたほうが良さそうだね
684デフォルトの名無しさん
2022/04/26(火) 13:29:24.27ID:v9kFaZ9R 変換するならばヒープ使わずに配列mapかな
match foo.map(String::as_str) はちょっと惜しかった
match foo.map(String::as_str) はちょっと惜しかった
685デフォルトの名無しさん
2022/04/26(火) 14:28:08.93ID:9/mVSM+b 配列mapだと元のStringがdropされるから&str作れないのでは
686デフォルトの名無しさん
2022/04/26(火) 15:51:55.40ID:y3S6RL/9 配列mapは別の配列となる
元は消えないのでdropはされない
元は消えないのでdropはされない
687デフォルトの名無しさん
2022/04/26(火) 16:05:15.07ID:MauoWn9e 別の配列になるけど
mapがなぜかselfを要求する
つまりStringの配列に対して何もできない
Stringの長さの配列すら生成不可能
Copy実装型の配列に対してしかmapを使えないのではないか
mapがなぜかselfを要求する
つまりStringの配列に対して何もできない
Stringの長さの配列すら生成不可能
Copy実装型の配列に対してしかmapを使えないのではないか
689デフォルトの名無しさん
2022/04/26(火) 16:57:38.42ID:o3+/PYQ+ >>688
配列mapはイテレータとは無関係
配列mapはイテレータとは無関係
691デフォルトの名無しさん
2022/04/26(火) 17:08:44.26ID:9/mVSM+b >>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な型に対してしか使えないということはないよ
例えば構造体の一部フィールドだけ変更するみたいな用途にも使える
長さの配列は元の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な型に対してしか使えないということはないよ
例えば構造体の一部フィールドだけ変更するみたいな用途にも使える
692デフォルトの名無しさん
2022/04/26(火) 17:13:18.82ID:6GFvJMAy each_ref()を使えばできるよ
693デフォルトの名無しさん
2022/04/26(火) 17:20:49.70ID:6GFvJMAy &strの配列に変換してから比較すると変換時と比較時とで2周するのと
比較対象がconst相当じゃないとだめなのでguardのほうがベターなケースが多いと思う
比較対象がconst相当じゃないとだめなのでguardのほうがベターなケースが多いと思う
694デフォルトの名無しさん
2022/04/26(火) 17:38:44.61ID:+plNly3p 配列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:?}"); // エラーとならず元の配列も残っている
つまり配列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:?}"); // エラーとならず元の配列も残っている
695デフォルトの名無しさん
2022/04/26(火) 18:27:08.74ID:rgPp8Pfc 意味不明な解説だな
「array::mapはselfを要求する」の一言で済む話だろ
「array::mapはselfを要求する」の一言で済む話だろ
696デフォルトの名無しさん
2022/04/26(火) 18:33:28.01ID:WcuXDkX5 配列mapは
Stringの配列を&strの配列に変換できないけど
&Stringの配列を&strの配列に変換できるよ
つまり
Stringの配列を&Stringの配列に変換できればよくてそれがeach_ref()
Stringの配列を&strの配列に変換できないけど
&Stringの配列を&strの配列に変換できるよ
つまり
Stringの配列を&Stringの配列に変換できればよくてそれがeach_ref()
697デフォルトの名無しさん
2022/04/26(火) 19:46:56.99ID:/uwAuiMA 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 };
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 };
698デフォルトの名無しさん
2022/04/26(火) 21:05:30.47ID:FU096Fs4 こういう何がしたいのか分かりにくいだけのコードは勘弁して欲しいな
699デフォルトの名無しさん
2022/04/26(火) 21:13:08.58ID:YFyFIjJ4 iter→map→collectだけのコードが分かりにくい、って初心者でも言わないだろw
3行目の数値1と2は謎だが>>679の質問者のコードそのままだな
3行目の数値1と2は謎だが>>679の質問者のコードそのままだな
700デフォルトの名無しさん
2022/04/26(火) 21:47:45.37ID:ttl254Ty mapの中身は(|s| s.as_str())にしたいな
初心者だけど&**sはちょっと分かりにくい
初心者だけど&**sはちょっと分かりにくい
701デフォルトの名無しさん
2022/04/26(火) 21:55:49.66ID:zrm7en4p そういう視点ならば
match &y[..] のところも
match y.as_slice() にする?
match &y[..] のところも
match y.as_slice() にする?
702デフォルトの名無しさん
2022/04/26(火) 23:09:05.06ID:Nz4IrK9J そこまでしてやるメリットが全くない
matchでやるならマッチガード一択
matchでやるならマッチガード一択
703デフォルトの名無しさん
2022/04/26(火) 23:34:34.80ID:sIujHvVn704デフォルトの名無しさん
2022/04/27(水) 04:56:28.33ID:bvfmGeJD うーんRustのコンパイルエラーは素晴らしいな
705デフォルトの名無しさん
2022/04/27(水) 06:27:18.74ID:4nwYgCZM rustのジェネリックでSystemCみたいなのって書ける?
C#だと無理っぽいんだけど
C#だと無理っぽいんだけど
706デフォルトの名無しさん
2022/04/27(水) 10:03:29.93ID:wZJ3zy1g 定数パラメータなら最近サポートされた
#[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]);
はできなかった
#[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]);
はできなかった
707デフォルトの名無しさん
2022/04/27(水) 11:10:01.91ID:zNaA7U6C 演算子 ? のことを個人的にトライ演算子と呼んでいたんですが、
公式には単に「operator ?」としか書いていないみたいですね。
口頭で言うときにはどういう言い方で呼びます?
公式には単に「operator ?」としか書いていないみたいですね。
口頭で言うときにはどういう言い方で呼びます?
708デフォルトの名無しさん
2022/04/27(水) 11:16:36.97ID:2jBbs2Yc https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator
一応公式はquestion mark operatorとのこと
日本語で口頭だと、はてな演算子って言っちゃうかな
一応公式はquestion mark operatorとのこと
日本語で口頭だと、はてな演算子って言っちゃうかな
709デフォルトの名無しさん
2022/04/27(水) 11:26:22.90ID:zNaA7U6C >>708
他は機能で名前が付いているのにそれだけ字面を元にした名前なんですね。
他は機能で名前が付いているのにそれだけ字面を元にした名前なんですね。
710デフォルトの名無しさん
2022/04/27(水) 11:32:02.01ID:Xa5DwGtB try-catchが将来入ることを考えると、 ? の役割は try と言うより throw 相当と考えた方が良いのかな
711デフォルトの名無しさん
2022/04/27(水) 11:42:11.93ID:6hfejJV6 >>709
question markそのものにYes/Noの2択を突きつける意味があるからだろうな
question markそのものにYes/Noの2択を突きつける意味があるからだろうな
712デフォルトの名無しさん
2022/04/27(水) 12:31:18.25ID:QnhXU+83713デフォルトの名無しさん
2022/04/27(水) 13:12:23.42ID:yb/peNBg Cowにmapがほしい
714デフォルトの名無しさん
2022/04/27(水) 13:58:49.07ID:xkktFfcp 前置ならtryのままでもよかったんだろうけどね
715デフォルトの名無しさん
2022/04/27(水) 14:44:12.78ID:mvVxShyZ 後置でメソッドチェーンと相性よくなった
716デフォルトの名無しさん
2022/04/27(水) 15:54:47.56ID:zNaA7U6C 後置にするにしても普通のメソッドみたいになんらかの名前で呼び出すようにしたら
それがプログラムの流れを変える制御構文的なものであることが分かり難くなるだろうし、
後置の演算子という選択はとても良いと思う。
それがプログラムの流れを変える制御構文的なものであることが分かり難くなるだろうし、
後置の演算子という選択はとても良いと思う。
717デフォルトの名無しさん
2022/04/27(水) 16:00:03.30ID:fXEX2s7j718デフォルトの名無しさん
2022/04/27(水) 16:17:57.00ID:QP7+22WQ >>716
後置の演算子にするのはRustの使い方なら当然だと思うが
声に出して読めない(人によって読み方がバラバラになってる)のが問題
try file.read()時代は誰でも同じように読めた
file.read()? は読めない
.awaitはオペレータを導入したとしてもawaitオペレータという呼び方でみんな同じように読めるから何の問題もない
後置の演算子にするのはRustの使い方なら当然だと思うが
声に出して読めない(人によって読み方がバラバラになってる)のが問題
try file.read()時代は誰でも同じように読めた
file.read()? は読めない
.awaitはオペレータを導入したとしてもawaitオペレータという呼び方でみんな同じように読めるから何の問題もない
719デフォルトの名無しさん
2022/04/27(水) 16:26:14.46ID:nimuFt37 file.read().await? よりも
file.read()待? でいいんじゃないかな
オペレータ記号は仮に「待」とした
file.read()待? でいいんじゃないかな
オペレータ記号は仮に「待」とした
720デフォルトの名無しさん
2022/04/27(水) 16:32:03.42ID:Xa5DwGtB 演算子として使える記号残ってる?
721デフォルトの名無しさん
2022/04/27(水) 19:33:26.91ID:quTQsckx722デフォルトの名無しさん
2022/04/27(水) 19:36:30.61ID:Xa5DwGtB Cow::to_mut() じゃだめ?
723デフォルトの名無しさん
2022/04/27(水) 19:42:04.29ID:du++GsRu724デフォルトの名無しさん
2022/04/28(木) 10:44:53.84ID:9IEjG0GC バイナリデータを受け取るいい方法ってある?
やりたいことはGETリクエストの結果送られてくるバイナリデータをファイルに保存したい
CやJavaなら適当なchar配列(Javsはbyte)でいっぱいまで受け取ってファイルに書き出すを繰り返せばいいってわかるんだけど、似たようなことをRustでやりたい
やりたいことはGETリクエストの結果送られてくるバイナリデータをファイルに保存したい
CやJavaなら適当なchar配列(Javsはbyte)でいっぱいまで受け取ってファイルに書き出すを繰り返せばいいってわかるんだけど、似たようなことをRustでやりたい
725デフォルトの名無しさん
2022/04/28(木) 11:03:14.51ID:ZJVxwbem726デフォルトの名無しさん
2022/04/28(木) 11:12:32.29ID:9IEjG0GC ありがとう
やってみる
やってみる
727デフォルトの名無しさん
2022/04/28(木) 11:40:54.23ID:ZJVxwbem 綺麗に抽象化したレイヤを作ろうとしたら C や Java とは違った雰囲気にはなるだろうけど、そういうのは後回しや。
綺麗だろうが汚かろうがまずはやってみたらええんや。
ところで「汚かろう」を変換したら「北中朗」と出てきた。 誰やお前は。
綺麗だろうが汚かろうがまずはやってみたらええんや。
ところで「汚かろう」を変換したら「北中朗」と出てきた。 誰やお前は。
728デフォルトの名無しさん
2022/04/29(金) 00:19:46.61ID:H/gm+2Cv 勉強中
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
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
729デフォルトの名無しさん
2022/04/30(土) 03:53:42.52ID:cIBooLV/ 16進数文字列から整数への変換を標準ライブラリでやるにはどうすればよいですか?
730デフォルトの名無しさん
2022/04/30(土) 07:53:08.90ID:tlhDM02s Cだと次のように書けるエンディアンを調べるプログラムはどう書いたらいいですか?
int x = 0x12345678;
char *p = &x;
for( int i = 0; i< sizeof(int); i++ ){
fprintf(stderr, "%X\n", *p++ );
}
CでもWarningは出ますが
int x = 0x12345678;
char *p = &x;
for( int i = 0; i< sizeof(int); i++ ){
fprintf(stderr, "%X\n", *p++ );
}
CでもWarningは出ますが
731デフォルトの名無しさん
2022/04/30(土) 09:38:22.42ID:2I/Bonq2732デフォルトの名無しさん
2022/04/30(土) 19:04:20.68ID:1Px+JTey >>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) });
}
}
どうしても表示したいならば
直訳するとこんな感じ
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) });
}
}
733デフォルトの名無しさん
2022/04/30(土) 22:34:14.48ID:jfGNsSDk 原則としてはエンディアンに依存しない形で書いて入出力のときだけ from_le とか to_le とかで処理するのが良い作法だとは思うけどね……。
734デフォルトの名無しさん
2022/04/30(土) 23:10:52.66ID:prwxQRGd >>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"));
}
仕様がわからないからジェネリックに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"));
}
735デフォルトの名無しさん
2022/04/30(土) 23:19:42.84ID:xinPqoeI736デフォルトの名無しさん
2022/05/01(日) 09:25:29.21ID:WWrQ89FM >>734
がんばりすぎw
がんばりすぎw
737デフォルトの名無しさん
2022/05/01(日) 13:20:24.87ID:R2/wU8kY >>734 これ標準ライブラリにあるで
use std::usize;
fn main() {
let z = usize::from_str_radix("ffff", 16).unwrap();
assert_eq!(z, 65535);
}
use std::usize;
fn main() {
let z = usize::from_str_radix("ffff", 16).unwrap();
assert_eq!(z, 65535);
}
738デフォルトの名無しさん
2022/05/01(日) 18:53:34.40ID:AHIbQu1a 現状の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()に統一できる
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()に統一できる
739デフォルトの名無しさん
2022/05/01(日) 20:49:11.67ID:4fkon5Y4 u128でもfrom_str_radix使えるのはさておき
便利そうだけどそんなtraitにFromStrという名前が付くのは違和感あるなあ
便利そうだけどそんなtraitにFromStrという名前が付くのは違和感あるなあ
740デフォルトの名無しさん
2022/05/01(日) 21:11:45.93ID:RoZQG5Cx741デフォルトの名無しさん
2022/05/01(日) 21:14:33.66ID:Z7VnuZFm >>740
FromStrなのにSelf以外の型に変換されるのが違和感あるということでは
FromStrなのにSelf以外の型に変換されるのが違和感あるということでは
742デフォルトの名無しさん
2022/05/01(日) 21:15:48.33ID:Z7VnuZFm T::from_str が T (Result<T, E>) 以外の型を返す関数なのは違和感あるでしょってことが言いたかった
743デフォルトの名無しさん
2022/05/01(日) 21:41:43.18ID:PdC+0ci4 Radix<u128, 16>::from_str が Radix<u128, 16> を返してもいいだろうけど
中身はu128しかないのだから FromStr<Output = u128> で u128 を返せると便利、って話だよね
XXX::from_str の XXX 部分は文字列をどう解釈するかの指定
だから通常は Output = XXX と同一になるけど、そこを指定できると互換性を保ったまま利便性を向上できるという話だよね
中身はu128しかないのだから FromStr<Output = u128> で u128 を返せると便利、って話だよね
XXX::from_str の XXX 部分は文字列をどう解釈するかの指定
だから通常は Output = XXX と同一になるけど、そこを指定できると互換性を保ったまま利便性を向上できるという話だよね
744デフォルトの名無しさん
2022/05/01(日) 22:19:59.78ID:Z7VnuZFm 提案自体は分かるけど T from str と読めるメソッドが T 以外の何者かを返すのは不適切な命名では?
別のtraitでやるべきだと思う
別のtraitでやるべきだと思う
745デフォルトの名無しさん
2022/05/01(日) 22:44:03.61ID:4fkon5Y4 >>741
そういうこと
不用意に複雑にするのはよろしくないし、stdにある必要も無いと思う
どうしてもやりたければ↓みたいに自分で実装できるし、
もっと複雑になってきたら適切なパーサライブラリでも使用するのがいいだろう
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f450a3bdf5eab0f1849b4945aede582f
そういうこと
不用意に複雑にするのはよろしくないし、stdにある必要も無いと思う
どうしてもやりたければ↓みたいに自分で実装できるし、
もっと複雑になってきたら適切なパーサライブラリでも使用するのがいいだろう
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f450a3bdf5eab0f1849b4945aede582f
746デフォルトの名無しさん
2022/05/01(日) 23:00:56.52ID:4fkon5Y4 ところでこれ書いてて気づいたけど i8::from_str_radix("80", 16) とかは PosOverflow になるんですね
16 だからできそうな気がするだけで、考えてみればそうかという感じだけど
16 だからできそうな気がするだけで、考えてみればそうかという感じだけど
747デフォルトの名無しさん
2022/05/01(日) 23:26:05.49ID:fn7me9b4748デフォルトの名無しさん
2022/05/02(月) 02:54:31.42ID:9t4339jX749デフォルトの名無しさん
2022/05/02(月) 15:22:57.69ID:mbEFGeje cargo が粗悪
スグにリソースを喰らい尽くす特級禍呪怨霊
スグにリソースを喰らい尽くす特級禍呪怨霊
750デフォルトの名無しさん
2022/05/02(月) 15:33:08.28ID:nqnbrNKO >>749
メモリかCPUが足りないなら -j オプションつけるか
.cargo/config.toml の jobs 設定したら良いのでは
https://doc.rust-lang.org/cargo/reference/config.html
メモリかCPUが足りないなら -j オプションつけるか
.cargo/config.toml の jobs 設定したら良いのでは
https://doc.rust-lang.org/cargo/reference/config.html
751デフォルトの名無しさん
2022/05/02(月) 18:47:44.24ID:G4+2oPiW どちらも参照で構造体のオプションをそのメンバーのオプションにするもっと短い表記ないのかな
struct1.map(|struct1| struct1.member2)
struct1.map(|struct1| struct1.member2)
752デフォルトの名無しさん
2022/05/02(月) 22:42:33.85ID:gA2l3mfi どちらも参照とは?
753デフォルトの名無しさん
2022/05/02(月) 23:24:08.49ID:J2M173NZ メンバーを参照で返すならば
&struct1.member2 と&が必要
元のOptionのstruct1はもし参照が外側ならば
struct1.as_ref() で内側の参照にしておくことが必要
&struct1.member2 と&が必要
元のOptionのstruct1はもし参照が外側ならば
struct1.as_ref() で内側の参照にしておくことが必要
754デフォルトの名無しさん
2022/05/03(火) 01:23:35.68ID:PKeASy9M struct1.map(|struct1| &struct1.member2)
長くていいなら
struct1.and_then(|struct1| Some(&struct1.member2))
長くていいなら
struct1.and_then(|struct1| Some(&struct1.member2))
755デフォルトの名無しさん
2022/05/03(火) 02:02:53.67ID:PFPUtHlZ すごく曖昧な日本語だけど普通に読むなら
構造体のオプションも、そのメンバーのオプションも、どちらも参照という意味じゃないの?
struct Foo<‘a> {
bar: &’a Option<Bar>
}
↑こういう構造体を&Option<Foo>の形で受け取って内包する&Option<Bar>で返したいという話
知らんけど
構造体のオプションも、そのメンバーのオプションも、どちらも参照という意味じゃないの?
struct Foo<‘a> {
bar: &’a Option<Bar>
}
↑こういう構造体を&Option<Foo>の形で受け取って内包する&Option<Bar>で返したいという話
知らんけど
756デフォルトの名無しさん
2022/05/03(火) 02:47:01.44ID:w0rxhNU2 これならstruct1が1回しか出てこなくて短い
(|| Some(&struct1?.member2))()
(|| Some(&struct1?.member2))()
757デフォルトの名無しさん
2022/05/03(火) 08:20:59.49ID:Kk3DPrDK■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 首相官邸前で「戦争あおるな」 台湾有事巡る答弁に抗議 [蚤の市★]
- 高市首相告白「『なめられない服』を選ぶことに数時間を費やしました」「外交交渉でマウント取れる服、買わなくてはいかんかもなぁ」 [ぐれ★]
- 国民・榛葉氏「中国焦ってる」 [ぐれ★]
- 【高市リスク】立民・小西洋之参院議員「高市総理がとんでもない安全保障オンチで外交オンチ」 [ぐれ★]
- 『DOWNTOWN+』会員数50万人突破で見えてきた 松本人志の“月収4ケタ万円”驚愕収入 [阿弥陀ヶ峰★]
- 中国、高市首相非難の漫画 在フィリピン大使館がXに投稿 [ぐれ★]
- 高市「財務省案はしょぼすぎる」経済対策自ら上乗せ、野党の要望も取り入れ予算規模拡大 [903292576]
- 日本人「憲法9条があれば侵略されないって叫んでた売国左翼のゴミどもは今どんな気分?😂wwwwww」 [441660812]
- 【んな専🏡】三連休もんなってんなってんなりまくるのらよ🍬(・o・🍬)🏰
- 朝から肉食いてえ
- 女死ね
- 【悲報】東京都民さん、20過ぎてるのに自転車に乗っててて大炎上wwwwwwwwwwww女「いい歳した男で自転車に乗るのは知的障がい者だけだよ? [483447288]
