質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

2回答

580閲覧

Rustで条件によって変数を定義するかしないかを分岐する方法

tasuren

総合スコア76

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2022/08/22 01:54

前提

Rustにて、条件によっては使うが、その条件によっては使わないという変数があるとします。
その変数を使わないのなら、その変数を作らない方がよりパフォーマンスが向上しそうです。
ですが、条件によって定義するしないをすることが一見できなそうです。
これをする方法はありますか?

実現したいこと

エラーが起きる以下のコードのようなことをしたい。

rust

1if more_info { 2 # より多くの情報が欲しい場合は、より多くの情報を計算するのに必要なキャッシュのための変数を作る。 3 let stack_for_more_info = Vec::new(); 4}; 5 6for data in datas { 7 ... 8 9 if more_info { 10 # より多くの情報を計算するためのデータを記憶する。 11 stack_for_more_info.push(...) 12 }; 13}; 14 15# より多くの情報を`stack_for_more_info`を元にして計算する。 16if more_info { ... }

発生している問題・エラーメッセージ

上記をすると、スコープにstack_for_more_infoという変数が存在しないというエラーが発生してしまいます。

試したこと

上の実現したいことにあるコードと、条件であるmore_infoの値に構わず変数を毎回定義して値を作るコードを試しました。
後者は動きますが、毎回変数を定義して使わない値を作ってしまいます。
また、これについてGoogleで検索するとif let ... = ... && 条件のような書き方がいつか使えるようになるというような情報がありました。
ですが、いつか使えると書いてあるように、今のstableではこの書き方は使えませんでした。

補足情報(FW/ツールのバージョンなど)

cargo 1.62.1 (a748cf5a3 2022-06-08) rustc 1.62.1 (e092d0b6b 2022-07-16)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんにちは。

タイトルにある変数を定義する(初期化する)かどうかを条件によって決めるだけなら変数宣言と初期化を分けてあげると可能です。

rust

1let stack_for_more_info; 2if more_info { 3 // より多くの情報が欲しい場合は、より多くの情報を計算するのに必要なキャッシュのための変数を作る。 4 stack_for_more_info = Vec::new(); 5};

しかしこれだと使用するときに未初期化変数かもということでエラーが出てしまいます。

error[E0381]: borrow of possibly-uninitialized variable: `stack_for_more_info` --> src/main.rs:15:13 | 15 | stack_for_more_info.push(1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `stack_for_more_info`

定義も使用も if more_info {...} で囲まれているので人間なら初期化済みと分かりますが、機械には(一般には)判定できないので一律でエラーになってしまいます。

こういう場合は Option を使って未初期化を表わすイディオムがあります。

rust

1let mut stack_for_more_info = None; 2if more_info { 3 // より多くの情報が欲しい場合は、より多くの情報を計算するのに必要なキャッシュのための変数を作る。 4 stack_for_more_info = Some(Vec::new()); 5}; 6 7for _data in datas { 8 // ... 9 if more_info { 10 // より多くの情報を計算するためのデータを記憶する。 11 // 目でNoneになることがないと分かるのでunwrapを使ってよい 12 stack_for_more_info.as_mut().unwrap().push(1) 13 }; 14}

未初期化を表わすのに None 、初期化済みなら Some 、初期化済みと分かって使うなら unwrap() とすることでやりたいことが達成できます。

動くコードをこちらに置いておきます。参考になれば

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5bbfb2373612903f2553708724dd71a5

投稿2022/08/22 23:58

blackenedgold

総合スコア468

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

言語の性質上そのようなコードは書けないと思います
vecの場合、初期化による処理は一般には気にしなくて良いほどのものなので、定義しても大丈夫です。
初期化が重い時にどうすれば、、、という場合はOptionなどを使ってあげると良いと思います。
(あとはコンパイラの最適化に期待しましょう)

投稿2022/08/22 10:35

eup

総合スコア29

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tasuren

2022/08/23 08:27

回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問