Bringing Paths Into Scope with the use Keyword - The Rust Programming Language
関数を呼び出す時にpathを全部書くのは不便だと感じるかもしれない。
use
キーワードでpathへのショートカットを作成できる。
crate rootに、use crate::front_of_house::hosting;
を追加した場合、そのスコープ内でhosting
が有効になる。
use
はuse
が記述されたスコープでのみ有効になるため、以下はエラーとなる。
mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } use crate::front_of_house::hosting; mod customer { pub fn eat_at_restaurant() { hosting::add_to_waitlist(); } }
問題を解決するには、use
をcustomer
の中に移動させるか、super::hosting
で親モジュールから参照させる。
慣用的なuseの使い方
use
で関数をスコープに持ち込む場合は、関数名まで持ち込むのではなく親モジュールを持ち込む。
こうすることでその関数がどのモジュールで定義されているかが明確になる。
一方、構造体、enum、その他のitemを持ち込む場合は、フルパスを指定する。
use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert(1, 2); }
このidiomに強い理由があるわけではないが、Rustのコードはこの形で読み書きされることに慣れている。
また、例外は同じ名前の2つのitemをスコープに持ち込む場合である。以下は異なる親モジュールを持つが、同じ名前のResult
型をスコープに持ち込む方法である。
use std::fmt; use std::io; fn function1() -> fmt::Result { // --snip-- } fn function2() -> io::Result<()> { // --snip-- }
asキーワードで新しい名前を与える
同じ名前の2つの型をスコープに持ち込む別の方法として、as
キーワードで新しいローカル名をつけることができる。
use std::fmt::Result; use std::io::Result as IoResult; fn function1() -> Result { // --snip-- } fn function2() -> IoResult<()> { // --snip-- }
pub useによる名前の再公開
use
ーワードで名前をスコープに持ち込むと、その名前は新しいスコープ内で非公開(プライベート)になる。pub
とuse
を組み合わせることで、その名前をあたかもそのコード内で定義されたかのように参照できるようにすることができる。この手法は「再公開(re-exporting)」と呼ばれる。
mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); }
pub use
にする前にadd_to_waitlist()
呼び出すには、外部コードはrestaurant::front_of_house::hosting::add_to_waitlist()
と指定する必要があり、またfront_of_house
をpublicにする必要があった。pub use
を使うことで、hosting
モジュールが再公開されたため、restaurant::hosting::add_to_waitlist()
で使用が可能になる。
外部パッケージの利用
rand
パッケージを使用する際、Cargo.tomlに rand = "0.8.5"
を追加した。
Cargoはcrates.ioからrand
パッケージとその依存関係をダウンロードし、我々のプロジェクトで使用できるようにする。
その後、rand
の定義をプロジェクトのスコープに取り込むために、以下のように use 文を追加する。ここでは、クレート名 rand を先頭に指定し、スコープに取り込みたいアイテムを列挙する。Rngトレイトをスコープに取り込み、rand::thread_rng 関数を呼び出す。
use rand::Rng; fn main() { let secret_number = rand::thread_rng().gen_range(1..=100); }
標準ライブラリstd
も我々のパッケージから見ると外部クレートの1つである。ただ、Rust言語に付属しているため、Cargo.tomlにstd
を記載する必要はない。しかし、itemをスコープに取り込む場合は、use
が必要になる。
use std::collections::HashMap;
ネストしたpathで巨大なuseリストを整理する
// --snip-- use std::cmp::Ordering; use std::io; // --snip--
以下のように書き換えることができる。
// --snip-- use std::{cmp::Ordering, io}; // --snip--
ネストしたpathは、pathのどのレベルでも使用できる。
use std::io; use std::io::Write;
↓
use std::io::{self, Write};
glob演算子
use std::collections::*;
glob演算子を使うと、どの名前がスコープ内にあり、プログラムで使用される名前がどこで定義されたのかが分かりづらくなるため、注意が必要である。