1636017240
これまで、プログラムを単一ファイルモジュールとして作成してきました。しかし、プログラムが成長するにつれて、コードを複数のモジュール、ファイル、さらにはパッケージに編成することができます。
このモジュールでは、次のことを学びます。
コード編成の背後にある概念を理解する
始める前に、Rustプログラムのコード編成の背後にある概念を説明することが重要です。
Cargo.toml
ファイルにあります。コマンドを実行するたびに$ cargo new <project-name>
、Cargoはパッケージを作成します。
$ cargo new my-project
Created binary (application) `my-project` package
ここでは、のみを含むパッケージがあります。つまりsrc/main.rs
、my-project
:という名前のバイナリクレートのみが含まれています。
my-project
├── src
│ └── main.rs
└── Cargo.toml
ファイルをsrc/bin
ディレクトリに配置することにより、パッケージに複数のバイナリクレートを含めることができます。各ファイルは個別のバイナリクレートになります。
パッケージにsrc/main.rs
とが含まれている場合、src/lib.rs
ライブラリとバイナリの2つのクレートがあります。どちらもパッケージと同じ名前です。
Rustのコンパイルモデルは、バイナリまたはライブラリにコンパイルできるクレートと呼ばれるアーティファクトを中心としています。
cargo new
コマンドを使用して作成するすべてのプロジェクトは、それ自体がクレートです。プロジェクトの依存関係として使用できるすべてのサードパーティのRustコードも、それぞれ1つのクレートです。
バイナリプログラムの作成方法についてはすでに説明しましたが、ライブラリの作成も同様に簡単です。ライブラリを作成するには、--lib
コマンドラインパラメータを次のコマンドに渡しますcargo new
。
$ cargo new --lib my-library
Created library `my-library` package
src/main.rs
ファイルの代わりに、= src / lib.rs 'ファイルを取得していることがわかります。
my-library
├── src
│ └── lib.rs
└── Cargo.toml
Cargoにこのクレートをコンパイルするように指示するlibmy_library.rlib
と、他のプロジェクトに公開およびリンクできるというライブラリファイルが取得されます。
Rustは、コードを論理ユニットに階層的に分割するために使用できる強力なモジュールシステムを提供します。これにより、読みやすさと再利用も容易になります。
モジュールはアイテムのコレクションです。
impl
ブロックモジュールはアイテムのプライバシーも制御します。アイテムのプライバシーは、アイテムをパブリックまたはプライベートとして識別します。パブリックとは、アイテムが外部コードで使用できることを意味します。プライベートとは、アイテムが内部実装の詳細であり、外部で使用できないことを意味します。
モジュールの例:
mod math {
type Complex = (f64, f64);
pub fn sin(f: f64) -> f64 { /* ... */ }
pub fn cos(f: f64) -> f64 { /* ... */ }
pub fn tan(f: f64) -> f64 { /* ... */ }
}
println!("{}", math::cos(45.0));
ソースファイルにmod
宣言が含まれている場合、モジュールファイルの内容はmod
、コンパイラを実行する前に、ソースファイルの宣言が見つかった場所に挿入されます。つまり、モジュールは個別にコンパイルされるのではなく、クレートのみがコンパイルされます。
モジュールのpub
関数定義の先頭にあるキーワードに気付いたかもしれませんmath
。
Rustコンパイラは、アイテムがモジュール間で使用できるかどうかを確認します。デフォルトでは、Rustのすべてがプライベートであり、現在のモジュールとその子孫のみがアクセスできます。対照的に、アイテムがとして宣言されているpub
場合、それは外の世界にアクセス可能であると考えることができます。例えば:
// Declare a private struct
struct Foo;
// Declare a public struct with a private field
pub struct Bar {
field: i32,
}
// Declare a public enum with two public variants
pub enum State {
PubliclyAccessibleVariant,
PubliclyAccessibleVariant2,
}
Rustのプライバシールールは、内部実装の詳細を隠しながら、パブリックAPIを公開するモジュール階層を作成するのに驚くほど強力です。
コードをモジュールに分割する
モジュールは、コードをより適切に整理するのに役立つだけでなく、値、タイプ、およびメソッドにプライバシーの保証も提供します。
簡略化された認証APIをモデル化したこの例を見てください。
mod authentication {
pub struct User {
username: String,
password_hash: u64,
}
impl User {
pub fn new(username: &str, password: &str) -> User {
User {
username: username.to_string(),
password_hash: hash_password(password),
}
}
}
fn hash_password(input: &str) -> u64 { /*...*/ }
}
fn main() {
let user = authentication::User::new("jeremy", "super-secret");
println!("The username is: {}", user.username);
println!("The password is: {}", user.password_hash);
}
上記のコードでauthentication
は、両方ともパブリックであるため、モジュールがUser
構造体にUser::new
メソッドを提供していることがわかります。キーワードに注目してくださいpub
。
このコードは、構造体からフィールドusername
とpassword_hash
フィールドにアクセスしようとするため、コンパイルに失敗しますUser
が、これらはプライベートです。コードを実行すると、次のエラーが発生します。
error[E0616]: field `username` of struct `User` is private
--> src/main.rs:28:42
|
28 | println!("The username is: {}", user.username);
| ^^^^^^^^ private field
error[E0616]: field `password_hash` of struct `User` is private
--> src/main.rs:29:42
|
29 | println!("The password is: {}", user.password_hash);
| ^^^^^^^^^^^^^ private field
error: aborting due to 2 previous errors
このエラー情報は、プログラムのどの部分が特定のモジュールの各部分にアクセスできるかを制御する場合に役立ちます。username
フィールドへの読み取りアクセスとフィールドへの書き込みアクセスをpassword
プライベートに保ちながら許可したい場合は、getterメソッドとsetterメソッドを使用できます。
mod authentication {
// ...
impl User {
// ...
pub fn get_username(&self) -> &String {
&self.username
}
pub fn set_password(&mut self, new_password: &str) {
self.password_hash = hash_password(new_password)
}
}
}
モジュールを異なるファイルに分割する
モジュールの内容が大きくなりすぎると、コードのナビゲーションがより困難になります。モジュールの内容を別のファイルに移動することを検討してください。
前の例からと呼ばれる独自のファイルにコードを移動してからsrc/authentication.rs
、クレートルートファイルを変更してみましょう。
ファイル名:src / main.rs
mod authentication;
fn main() {
let mut user = authentication::User::new("jeremy", "super-secret");
println!("The username is: {}", user.get_username());
user.set_password("even-more-secret");
}
ファイル名:src / authentication.rs
pub struct User {
username: String,
password_hash: u64,
}
impl User {
pub fn new(username: &str, password: &str) -> User {
User {
username: username.to_string(),
password_hash: hash_password(&password.to_owned()),
}
}
pub fn get_username(&self) -> &String {
&self.username
}
pub fn set_password(&mut self, new_password: &str) {
self.password_hash = hash_password(&new_password.to_owned())
}
}
fn hash_password<T: Hash>(t: &T) -> u64 {/* ... */}
mod authentication
コードブロックの代わりにセミコロンを後に配置します。ファイルのサイズが大きくなると、この手法を使用してモジュールを新しいファイルに自動的に移動できます。コンパイラは、モジュールと同じ名前の別のファイルからモジュールの内容をロードします。
コンテンツがロードされるとき、モジュールツリーは同じままです。定義が別のファイルに存在する場合でも、コードは変更を必要とせずに機能します。
プロジェクトにサードパーティのクレートを追加する
このモジュールでは、サードパーティのクレートをプロジェクトに追加する方法を学習します。Rust標準ライブラリには正規表現用のモジュールがないためregex
、Crates.ioで入手できるクレートを追加しましょう。このWebサイトは、Rustコミュニティの中央パッケージレジストリであり、パッケージを検出してダウンロードする場所として機能します。
プロジェクトに依存する木枠を追加したいときはいつでも、Cargoに頼ってすべての面倒な作業を行うことができます。crates.ioでホストされているライブラリに依存するには、それをCargo.toml
ファイルに追加します。
[dependencies]
regex = "1.4.2"
Cargo.toml
まだ[dependencies]
セクションがない場合は、そのセクションを追加します。次に、使用するクレート名とバージョンをリストします。
次のステップは、コマンドを実行することcargo build
です。Cargoは、新しい依存関係とそのすべての依存関係をフェッチし、それらをすべてコンパイルします。
$ cargo build
Updating crates.io index
Downloaded regex v1.4.2
Downloaded thread_local v1.0.1
Downloaded regex-syntax v0.6.21
Downloaded lazy_static v1.4.0
Downloaded aho-corasick v0.7.15
Downloaded memchr v2.3.4
Downloaded 6 crates (689.7 KB) in 4.58s
Compiling memchr v2.3.4
Compiling lazy_static v1.4.0
Compiling regex-syntax v0.6.21
Compiling thread_local v1.0.1
Compiling aho-corasick v0.7.15
Compiling regex v1.4.2
Compiling my-project v0.1.0 (/home/user/code/my-project)
Finished dev [unoptimized + debuginfo] target(s) in 35.13s
これで、regex
ライブラリを次の場所で使用できますmain.rs
。
use regex::Regex;
fn main() {
let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
println!("Did our date match? {}", re.is_match("2014-01-01"));
}
実行すると、次のように表示されます。
$ cargo run
Running `target/hello_world`
Did our date match? true
また、中に、サードパーティ製の箱を使用することができ錆遊び場。
演習-可視性
特に明記されていない限り、モジュール内のすべてのアイテムはプライベートです。モジュールスコープ外からアクセスできるのは、モジュールのパブリックアイテムのみです。
次のコードにはコンパイラエラーがあります。この演習での割り当ては、main
関数を変更せずにコードを正常にコンパイルすることです。
mod car_factory {
fn build_car() {
println!("Honk honk!");
}
}
fn main() {
car_factory::build_car();
}
ヒント:コンパイラエラーは、公開する必要のあるアイテムを指している必要があります。
関数と可視性でモジュールを使用することについて学んだことを使用するチャンスです。
次のコードには、いくつかのコンパイラエラーがあります。この演習での割り当ては、main
関数を変更せずにコードを正常にコンパイルすることです。
mod text_processing {
mod letters {
fn count_letters(text: &str) -> usize {
text.chars().filter(|ref c| c.is_alphabetic()).count()
}
}
mod numbers {
fn count_numbers(text: &str) -> usize {
text.chars().filter(|ref c| c.is_numeric()).count()
}
}
}
fn count_letters_and_numbers(text: &str) -> (usize, usize) {
let number_of_letters = ???;
let number_of_numbers = ???;
(number_of_letters, number_of_numbers)
}
fn main() {
assert_eq!(count_letters_and_numbers("221B Baker Street"), (12, 3));
assert_eq!(count_letters_and_numbers("711 Maple Street"), (11, 3));
assert_eq!(count_letters_and_numbers("4 Privet Drive"), (11, 1));
}
概要
このモジュールでは、次のことを学びました。
リンク: https://docs.microsoft.com/en-us/learn/modules/rust-modules-packages-crates/
1636017240
これまで、プログラムを単一ファイルモジュールとして作成してきました。しかし、プログラムが成長するにつれて、コードを複数のモジュール、ファイル、さらにはパッケージに編成することができます。
このモジュールでは、次のことを学びます。
コード編成の背後にある概念を理解する
始める前に、Rustプログラムのコード編成の背後にある概念を説明することが重要です。
Cargo.toml
ファイルにあります。コマンドを実行するたびに$ cargo new <project-name>
、Cargoはパッケージを作成します。
$ cargo new my-project
Created binary (application) `my-project` package
ここでは、のみを含むパッケージがあります。つまりsrc/main.rs
、my-project
:という名前のバイナリクレートのみが含まれています。
my-project
├── src
│ └── main.rs
└── Cargo.toml
ファイルをsrc/bin
ディレクトリに配置することにより、パッケージに複数のバイナリクレートを含めることができます。各ファイルは個別のバイナリクレートになります。
パッケージにsrc/main.rs
とが含まれている場合、src/lib.rs
ライブラリとバイナリの2つのクレートがあります。どちらもパッケージと同じ名前です。
Rustのコンパイルモデルは、バイナリまたはライブラリにコンパイルできるクレートと呼ばれるアーティファクトを中心としています。
cargo new
コマンドを使用して作成するすべてのプロジェクトは、それ自体がクレートです。プロジェクトの依存関係として使用できるすべてのサードパーティのRustコードも、それぞれ1つのクレートです。
バイナリプログラムの作成方法についてはすでに説明しましたが、ライブラリの作成も同様に簡単です。ライブラリを作成するには、--lib
コマンドラインパラメータを次のコマンドに渡しますcargo new
。
$ cargo new --lib my-library
Created library `my-library` package
src/main.rs
ファイルの代わりに、= src / lib.rs 'ファイルを取得していることがわかります。
my-library
├── src
│ └── lib.rs
└── Cargo.toml
Cargoにこのクレートをコンパイルするように指示するlibmy_library.rlib
と、他のプロジェクトに公開およびリンクできるというライブラリファイルが取得されます。
Rustは、コードを論理ユニットに階層的に分割するために使用できる強力なモジュールシステムを提供します。これにより、読みやすさと再利用も容易になります。
モジュールはアイテムのコレクションです。
impl
ブロックモジュールはアイテムのプライバシーも制御します。アイテムのプライバシーは、アイテムをパブリックまたはプライベートとして識別します。パブリックとは、アイテムが外部コードで使用できることを意味します。プライベートとは、アイテムが内部実装の詳細であり、外部で使用できないことを意味します。
モジュールの例:
mod math {
type Complex = (f64, f64);
pub fn sin(f: f64) -> f64 { /* ... */ }
pub fn cos(f: f64) -> f64 { /* ... */ }
pub fn tan(f: f64) -> f64 { /* ... */ }
}
println!("{}", math::cos(45.0));
ソースファイルにmod
宣言が含まれている場合、モジュールファイルの内容はmod
、コンパイラを実行する前に、ソースファイルの宣言が見つかった場所に挿入されます。つまり、モジュールは個別にコンパイルされるのではなく、クレートのみがコンパイルされます。
モジュールのpub
関数定義の先頭にあるキーワードに気付いたかもしれませんmath
。
Rustコンパイラは、アイテムがモジュール間で使用できるかどうかを確認します。デフォルトでは、Rustのすべてがプライベートであり、現在のモジュールとその子孫のみがアクセスできます。対照的に、アイテムがとして宣言されているpub
場合、それは外の世界にアクセス可能であると考えることができます。例えば:
// Declare a private struct
struct Foo;
// Declare a public struct with a private field
pub struct Bar {
field: i32,
}
// Declare a public enum with two public variants
pub enum State {
PubliclyAccessibleVariant,
PubliclyAccessibleVariant2,
}
Rustのプライバシールールは、内部実装の詳細を隠しながら、パブリックAPIを公開するモジュール階層を作成するのに驚くほど強力です。
コードをモジュールに分割する
モジュールは、コードをより適切に整理するのに役立つだけでなく、値、タイプ、およびメソッドにプライバシーの保証も提供します。
簡略化された認証APIをモデル化したこの例を見てください。
mod authentication {
pub struct User {
username: String,
password_hash: u64,
}
impl User {
pub fn new(username: &str, password: &str) -> User {
User {
username: username.to_string(),
password_hash: hash_password(password),
}
}
}
fn hash_password(input: &str) -> u64 { /*...*/ }
}
fn main() {
let user = authentication::User::new("jeremy", "super-secret");
println!("The username is: {}", user.username);
println!("The password is: {}", user.password_hash);
}
上記のコードでauthentication
は、両方ともパブリックであるため、モジュールがUser
構造体にUser::new
メソッドを提供していることがわかります。キーワードに注目してくださいpub
。
このコードは、構造体からフィールドusername
とpassword_hash
フィールドにアクセスしようとするため、コンパイルに失敗しますUser
が、これらはプライベートです。コードを実行すると、次のエラーが発生します。
error[E0616]: field `username` of struct `User` is private
--> src/main.rs:28:42
|
28 | println!("The username is: {}", user.username);
| ^^^^^^^^ private field
error[E0616]: field `password_hash` of struct `User` is private
--> src/main.rs:29:42
|
29 | println!("The password is: {}", user.password_hash);
| ^^^^^^^^^^^^^ private field
error: aborting due to 2 previous errors
このエラー情報は、プログラムのどの部分が特定のモジュールの各部分にアクセスできるかを制御する場合に役立ちます。username
フィールドへの読み取りアクセスとフィールドへの書き込みアクセスをpassword
プライベートに保ちながら許可したい場合は、getterメソッドとsetterメソッドを使用できます。
mod authentication {
// ...
impl User {
// ...
pub fn get_username(&self) -> &String {
&self.username
}
pub fn set_password(&mut self, new_password: &str) {
self.password_hash = hash_password(new_password)
}
}
}
モジュールを異なるファイルに分割する
モジュールの内容が大きくなりすぎると、コードのナビゲーションがより困難になります。モジュールの内容を別のファイルに移動することを検討してください。
前の例からと呼ばれる独自のファイルにコードを移動してからsrc/authentication.rs
、クレートルートファイルを変更してみましょう。
ファイル名:src / main.rs
mod authentication;
fn main() {
let mut user = authentication::User::new("jeremy", "super-secret");
println!("The username is: {}", user.get_username());
user.set_password("even-more-secret");
}
ファイル名:src / authentication.rs
pub struct User {
username: String,
password_hash: u64,
}
impl User {
pub fn new(username: &str, password: &str) -> User {
User {
username: username.to_string(),
password_hash: hash_password(&password.to_owned()),
}
}
pub fn get_username(&self) -> &String {
&self.username
}
pub fn set_password(&mut self, new_password: &str) {
self.password_hash = hash_password(&new_password.to_owned())
}
}
fn hash_password<T: Hash>(t: &T) -> u64 {/* ... */}
mod authentication
コードブロックの代わりにセミコロンを後に配置します。ファイルのサイズが大きくなると、この手法を使用してモジュールを新しいファイルに自動的に移動できます。コンパイラは、モジュールと同じ名前の別のファイルからモジュールの内容をロードします。
コンテンツがロードされるとき、モジュールツリーは同じままです。定義が別のファイルに存在する場合でも、コードは変更を必要とせずに機能します。
プロジェクトにサードパーティのクレートを追加する
このモジュールでは、サードパーティのクレートをプロジェクトに追加する方法を学習します。Rust標準ライブラリには正規表現用のモジュールがないためregex
、Crates.ioで入手できるクレートを追加しましょう。このWebサイトは、Rustコミュニティの中央パッケージレジストリであり、パッケージを検出してダウンロードする場所として機能します。
プロジェクトに依存する木枠を追加したいときはいつでも、Cargoに頼ってすべての面倒な作業を行うことができます。crates.ioでホストされているライブラリに依存するには、それをCargo.toml
ファイルに追加します。
[dependencies]
regex = "1.4.2"
Cargo.toml
まだ[dependencies]
セクションがない場合は、そのセクションを追加します。次に、使用するクレート名とバージョンをリストします。
次のステップは、コマンドを実行することcargo build
です。Cargoは、新しい依存関係とそのすべての依存関係をフェッチし、それらをすべてコンパイルします。
$ cargo build
Updating crates.io index
Downloaded regex v1.4.2
Downloaded thread_local v1.0.1
Downloaded regex-syntax v0.6.21
Downloaded lazy_static v1.4.0
Downloaded aho-corasick v0.7.15
Downloaded memchr v2.3.4
Downloaded 6 crates (689.7 KB) in 4.58s
Compiling memchr v2.3.4
Compiling lazy_static v1.4.0
Compiling regex-syntax v0.6.21
Compiling thread_local v1.0.1
Compiling aho-corasick v0.7.15
Compiling regex v1.4.2
Compiling my-project v0.1.0 (/home/user/code/my-project)
Finished dev [unoptimized + debuginfo] target(s) in 35.13s
これで、regex
ライブラリを次の場所で使用できますmain.rs
。
use regex::Regex;
fn main() {
let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
println!("Did our date match? {}", re.is_match("2014-01-01"));
}
実行すると、次のように表示されます。
$ cargo run
Running `target/hello_world`
Did our date match? true
また、中に、サードパーティ製の箱を使用することができ錆遊び場。
演習-可視性
特に明記されていない限り、モジュール内のすべてのアイテムはプライベートです。モジュールスコープ外からアクセスできるのは、モジュールのパブリックアイテムのみです。
次のコードにはコンパイラエラーがあります。この演習での割り当ては、main
関数を変更せずにコードを正常にコンパイルすることです。
mod car_factory {
fn build_car() {
println!("Honk honk!");
}
}
fn main() {
car_factory::build_car();
}
ヒント:コンパイラエラーは、公開する必要のあるアイテムを指している必要があります。
関数と可視性でモジュールを使用することについて学んだことを使用するチャンスです。
次のコードには、いくつかのコンパイラエラーがあります。この演習での割り当ては、main
関数を変更せずにコードを正常にコンパイルすることです。
mod text_processing {
mod letters {
fn count_letters(text: &str) -> usize {
text.chars().filter(|ref c| c.is_alphabetic()).count()
}
}
mod numbers {
fn count_numbers(text: &str) -> usize {
text.chars().filter(|ref c| c.is_numeric()).count()
}
}
}
fn count_letters_and_numbers(text: &str) -> (usize, usize) {
let number_of_letters = ???;
let number_of_numbers = ???;
(number_of_letters, number_of_numbers)
}
fn main() {
assert_eq!(count_letters_and_numbers("221B Baker Street"), (12, 3));
assert_eq!(count_letters_and_numbers("711 Maple Street"), (11, 3));
assert_eq!(count_letters_and_numbers("4 Privet Drive"), (11, 1));
}
概要
このモジュールでは、次のことを学びました。
リンク: https://docs.microsoft.com/en-us/learn/modules/rust-modules-packages-crates/
1652808540
Pythonのプログラミングに関する情報を発信しているサプーです!
この動画はPythonのモジュール・パッケージについて解説しました。
・モジュールとは何か?
・パッケージとは何か?
・モジュールの使い方
・モジュールのインストールの仕方
これらについて説明しています💙
実際にPythonコードを動かして実演しているので、最後まで見てもらえたら嬉しいです😊
⭐️チャプター⭐️
0:00 今日のテーマ「Pythonのモジュール」
0:20 モジュールとは?
0:49 モジュールの使い方
3:32 モジュールの使い方実践
5:38 パッケージのインストール
6:53 エンディング