はい、承知いたしました。Rustでプログラミングを始めるための「Hello, world!」入門ガイドについて、約5000語の詳細な記事を作成します。
Rustでプログラミングを始めよう!「Hello, world!」入門ガイド
プログラミングの世界へようこそ!新しい言語を学ぶ旅は、しばしば短いフレーズを画面に表示することから始まります。それは「Hello, world!」。このシンプルなたった一行の出力は、あなたが開発環境を正しく設定し、基本的なツールを使いこなし、最初のコードを実行することに成功したという証であり、プログラミングの伝統的な儀式でもあります。
このガイドでは、今注目されているプログラミング言語「Rust」を使って、あなたの最初の「Hello, world!」プログラムを作成するまでの道のりを、初心者にもわかりやすく、そして可能な限り詳細に解説します。Rustは、その安全性、パフォーマンス、並行性といった特徴から、システムプログラミング、WebAssembly、組み込みシステムなど、幅広い分野で採用が進んでいます。学習曲線は少し急かもしれませんが、一度基本を掴めば、非常に堅牢で効率的なプログラムを書くことができるようになります。
さあ、Rustの素晴らしい世界へ、一緒に第一歩を踏み出しましょう。このガイドでは、単にコードを示すだけでなく、その背後にある概念、必要なツール、そしてなぜそのような手順を踏むのかについても詳しく掘り下げていきます。約5000語という長文になりますが、それだけ詳細な情報を詰め込んでいますので、じっくりと読み進めてください。
第1部: なぜRustなのか?プログラミング言語としてのRustの魅力
「Hello, world!」を始める前に、なぜRustを選ぶのか、その理由を知っておくことは、学習のモチベーションにつながります。Rustは比較的新しい言語ですが、多くの開発者から高い評価を得ています。その主な魅力は以下の点に集約されます。
- メモリ安全性とスレッド安全性: Rustの最大の特徴は、コンパイル時にメモリに関するエラー(ヌルポインタ、データ競合など)を検出できる強力な保証を提供することです。これは、いわゆる「ガベージコレクション」のような実行時コストを伴う仕組みに頼るのではなく、「所有権システム(Ownership System)」という独特の概念によって実現されています。これにより、C++のような低レベル言語で問題となりがちなメモリ関連のバグを排除しつつ、高いパフォーマンスを維持できます。並行処理におけるデータ競合もコンパイル時に防げるため、安全なマルチスレッドプログラミングが可能です。
- パフォーマンス: Rustは実行時コストが非常に少ない言語です。ガベージコレクタがなく、抽象化のコストも最小限に抑えられているため、CやC++と同等のパフォーマンスを発揮できます。CPUやメモリといったリソースを最大限に活用する必要があるシステムプログラム、ゲームエンジン、OS開発などに適しています。
- ゼロコスト抽象化: Rustは、高レベルな抽象化(例えば、イテレータやジェネリクス)を提供しますが、これらの抽象化を使用しても実行時のオーバーヘッドがほとんど発生しません。コンパイラが高度な最適化を行うため、抽象化を使うことによるパフォーマンス上のペナルティが最小限に抑えられています。
- 信頼性の高い並行性: 前述の所有権システムと型システムにより、複数のスレッドが同時にデータにアクセスする際のデータ競合を防ぐことができます。これにより、並行処理を含むプログラムを安全に、そして比較的容易に記述できます。
- 活発なコミュニティと優れたツール: Rustは活発なオープンソースコミュニティを持っています。公式ドキュメントは非常に充実しており、
rustup
(Rustツールチェインマネージャー) やcargo
(ビルドシステム・パッケージマネージャー) といった標準ツールは非常に使いやすく、開発効率を高めてくれます。エラーメッセージも親切で、初心者でも問題解決のヒントを得やすくなっています。 - モダンな言語機能: パターンマッチング、強力な列挙型(enum)、トレイト(trait)といったモダンな言語機能を備えており、表現力豊かで保守しやすいコードを書くことができます。
これらの特徴から、RustはWebサーバー、コマンドラインツール、ブロックチェーン、オペレーティングシステム、組み込みデバイス、WebAssemblyを利用したフロントエンド開発など、多岐にわたる分野で採用が進んでいます。あなたのプログラミングスキルを次のレベルに引き上げるために、Rustは非常に価値のある選択肢となるでしょう。
第2部: 「Hello, world!」の目標設定と全体像
このガイドの目標は、Rust開発環境をセットアップし、「Hello, world!」プログラムを作成して実行することです。具体的には、以下のステップを順に追っていきます。
- Rust開発環境のセットアップ: Rustツールチェイン(コンパイラ、標準ライブラリなど)をインストールします。これは主に
rustup
というツールを使って行います。 - 基本的なRustツールの確認: インストールされたRustコンパイラ (
rustc
) とビルドシステム/パッケージマネージャー (cargo
) が正しく動作するか確認します。 - 「Hello, world!」プログラムの作成 (手動): テキストエディタを使ってソースコードファイルを作成し、Rustのコードを記述します。
- プログラムのコンパイル (手動): Rustコンパイラ (
rustc
) を使って、ソースコードをコンピュータが実行できる形式(実行可能ファイル)に変換します。 - プログラムの実行 (手動): 生成された実行可能ファイルを実行し、「Hello, world!」という出力が表示されることを確認します。
- 「Hello, world!」プログラムの作成と実行 (Cargo): Rustプロジェクトの標準的な管理ツールである
cargo
を使って、より効率的にプロジェクトを作成、ビルド、実行する方法を学びます。 - 「Hello, world!」コードの詳細解説: 作成したRustコード
fn main() { println!("Hello, world!"); }
の各要素(関数、マクロ、文字列、文など)が何を意味するのかを詳しく理解します。 - コンパイルと実行の仕組み: ソースコードがどのようにして実行可能なプログラムになるのか、その舞台裏で何が起きているのかを簡潔に説明します。
- トラブルシューティング: よくある問題とその解決策を紹介します。
第3部: 開発環境のセットアップ
Rustでプログラミングを開始するには、まず必要なツールをコンピュータにインストールする必要があります。Rustの公式なインストール方法は、rustup
というツールチェインマネージャーを使うことです。rustup
は、様々なプラットフォーム(Windows, macOS, Linuxなど)に対応しており、Rustの異なるバージョン(安定版、ベータ版、ナイトリー版)やクロスコンパイルのためのターゲットなどを簡単に管理できます。
ここでは、Windows, macOS, Linuxのそれぞれについて、一般的なインストール手順を説明します。
3.1. rustup
のインストール
macOS および Linux の場合:
macOSまたはLinuxを使用している場合は、ターミナル(端末エミュレータ)を開き、以下のコマンドを実行するのが最も一般的です。
bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
このコマンドは以下のことを行います:
* curl
: ウェブからデータをダウンロードするためのコマンドです。
* --proto '=https' --tlsv1.2
: HTTPSプロトコルを使い、TLS 1.2以上のバージョンを使用することを指定し、安全な通信を保証します。
* -sSf
: -s
は進捗状況を表示しない(静かに)、-S
はエラーを表示する、-f
はエラーが発生した場合に終了する、というオプションです。
* https://sh.rustup.rs
: rustup
インストーラスクリプトのURLです。
* |
: パイプ演算子です。curl
コマンドの出力(スクリプトの内容)を次のコマンドの入力に渡します。
* sh
: 標準入力を受け取ってシェルスクリプトとして実行するコマンドです。
つまり、このコマンドは rustup
インストーラスクリプトをダウンロードし、それを直接シェルスクリプトとして実行します。
スクリプトが実行されると、インストールオプションについて尋ねられます。通常は、デフォルトのインストール設定で問題ありません。1
を入力してEnterキーを押すか、単にEnterキーを押してデフォルトを選択します。
“`text
Current installation options:
default host triple: x86_64-apple-darwin (or x86_64-unknown-linux-gnu)
default toolchain: stable
profile: default
modify PATH variable: yes
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
“`
インストールが完了すると、以下のようなメッセージが表示されます。
“`text
Rust is installed now. Great!
To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo’s bin directory.
To configure your current shell, run:
source $HOME/.cargo/env
“`
このメッセージが示すように、Rustツール(rustc
, cargo
, rustup
など)が利用できるようになるには、多くの場合、ターミナルを再起動するか、.cargo/env
ファイルを現在のシェルに読み込ませる必要があります。推奨されている source $HOME/.cargo/env
コマンドを実行するのが手っ取り早いです。
Windows の場合:
Windowsの場合、公式ウェブサイト https://www.rust-lang.org/tools/install にアクセスし、rustup-init.exe
をダウンロードするのが最も簡単です。
ダウンロードした rustup-init.exe
を実行します。コマンドプロンプトまたはPowerShellのウィンドウが開く場合があります。macOS/Linuxと同様に、インストールオプションについて尋ねられます。
“`text
Current installation options:
default host triple: x86_64-pc-windows-msvc
default toolchain: stable
profile: default
modify PATH variable: yes
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
“`
通常は、デフォルトのインストール設定(1
を入力してEnterまたは単にEnter)で問題ありません。
Windowsでは、RustはMicrosoft Visual C++ Build Toolsに依存します。インストーラーがこれが必要であると判断した場合、Visual Studioのビルドツールのインストールを促されるか、既にインストールされているか確認されます。もしインストールされていない場合は、別途インストールする必要があります。これは、Rustが生成するコードがC/C++のリンカーを使用するためです。Visual Studio Build Toolsは、Microsoftの公式サイトから無償でダウンロードできます。Rustのインストーラーは、Visual Studio Installerを起動して、必要なコンポーネント(通常は「C++ Build Tools」)を選択・インストールするように案内してくれるはずです。
インストールが完了したら、新しいコマンドプロンプトまたはPowerShellのウィンドウを開き直してください。これは、Rustの実行ファイルが追加されたパス(通常は %USERPROFILE%\.cargo\bin
)がシステムに反映されるためです。
3.2. インストールの確認
インストールが完了し、新しいターミナルまたはコマンドプロンプトを開き直したら、RustコンパイラとCargoが正しくインストールされたか確認します。
以下のコマンドを実行してください。
bash
rustc --version
cargo --version
それぞれ、インストールされた rustc
および cargo
のバージョン情報が表示されるはずです。例えば、以下のような出力が得られます(バージョン番号は異なります)。
text
rustc 1.70.0 (e5a9b4bb2 2023-05-31)
cargo 1.70.0 (ec8a8a177 2023-04-25)
もしこれらのコマンドが認識されない(”command not found”のようなエラーが表示される)場合は、システムの環境変数 PATH
が正しく設定されていないか、ターミナルを再起動していない可能性があります。
* ターミナル/コマンドプロンプトを完全に閉じて開き直してみてください。
* macOS/Linuxの場合、インストール完了時に表示された source $HOME/.cargo/env
を実行したか確認してください。または、.bashrc
, .zshrc
, .profile
などのシェル設定ファイルに $HOME/.cargo/bin
がPATHに追加されているか確認し、ファイルに変更を加えた場合は source
コマンドで再読み込みするか、ターミナルを再起動してください。
* Windowsの場合、システム環境変数のPATHに %USERPROFILE%\.cargo\bin
が追加されているか確認してください。通常、rustup-init.exe
が自動で行いますが、手動で確認・設定が必要な場合もあります。
バージョン情報が表示されれば、Rust開発環境のセットアップは成功です!これで最初のRustプログラムを作成する準備が整いました。
第4部: 「Hello, world!」プログラムの作成と実行 (手動)
まずは、Rustの基本的なコンパイルと実行のワークフローを理解するために、Cargoを使わずに手動で「Hello, world!」プログラムを作成し、コンパイル・実行してみましょう。
4.1. プロジェクトディレクトリの作成
プログラムのソースコードを置くための新しいディレクトリを作成します。ターミナルまたはコマンドプロンプトで、以下のコマンドを実行してください。
bash
mkdir hello_world_manual
cd hello_world_manual
これは hello_world_manual
という名前の新しいディレクトリを作成し、そのディレクトリに移動するコマンドです。ディレクトリ名は任意ですが、ここではこのようにします。
4.2. ソースコードファイルの作成
次に、Rustのソースコードを記述するファイルを作成します。Rustのソースコードファイルは通常 .rs
という拡張子を持ちます。今回は main.rs
というファイル名で作成します。多くのプログラミング言語と同様に、Rustプログラムの実行開始点は main
という名前の関数です。慣習として、この main
関数を含むファイルを main.rs
とすることが多いです。
作成した hello_world_manual
ディレクトリ内で、お好みのテキストエディタを使って main.rs
という名前のファイルを作成してください。Visual Studio Code, Sublime Text, Atom, Vim, Nano など、どんなエディタでも構いません。
ファイルを作成したら、以下のコードを正確に記述してください。
rust
fn main() {
println!("Hello, world!");
}
コードを記述したら、ファイルを保存します。
4.3. コードの説明 (簡易版)
この短いコードについて、簡単に説明します。
fn main()
: これはmain
という名前の関数を定義しています。fn
キーワードは関数定義の開始を示します。main
関数は特別な関数で、Rustの実行可能プログラムはここから実行が開始されます。丸括弧()
はこの関数が引数を取らないことを意味します。波括弧{}
は関数の本体(実行されるコードブロック)を示します。println!("Hello, world!");
: これは画面にテキストを表示するための命令です。println!
はRustの「マクロ」と呼ばれる機能です。マクロは通常の関数とは少し異なり、コンパイル時にコードを生成する強力な仕組みです(詳細は後述します)。"Hello, world!"
は表示したい文字列です。ほとんどのRustの「文(statement)」はセミコロン;
で終わる必要があります。このprintln!
マクロの呼び出しも文なので、最後に;
がついています。
これで、あなたの最初のRustプログラムのソースコードが完成しました。
4.4. プログラムのコンパイル
ソースコードは人間が理解しやすい形式ですが、コンピュータは直接理解できません。コンピュータが実行できる形式(機械語)に変換する必要があります。この変換を行うのが「コンパイラ」です。Rustのコンパイラは rustc
です。
hello_world_manual
ディレクトリにいることを確認し、ターミナルまたはコマンドプロンプトで以下のコマンドを実行して、main.rs
ファイルをコンパイルします。
bash
rustc main.rs
このコマンドを実行すると、rustc
コンパイラが main.rs
ファイルを読み込み、コードに誤りがないかチェックし(構文エラー、型エラー、所有権エラーなど)、問題がなければコンパイル済みの実行可能ファイルを生成します。
コンパイルが成功した場合、特に何もメッセージは表示されません。エラーが発生した場合は、コンパイラが親切なエラーメッセージを表示してくれます。例えば、セミコロンを忘れた場合などは、エラー箇所とその理由が詳細に表示されるでしょう。
コンパイルが成功すると、同じディレクトリ内に新しいファイルが作成されます。
* Windows: main.exe
という名前のファイルが作成されます。
* macOS および Linux: main
という名前のファイルが作成されます(ファイル拡張子はありません)。
このファイルが、コンパイル済みの実行可能プログラムです。
4.5. プログラムの実行
コンパイルによって生成された実行可能ファイルを、ターミナルまたはコマンドプロンプトから実行します。
-
Windows:
cmd
main.exeまたは単に
cmd
main -
macOS および Linux:
bash
./mainLinuxやmacOSでは、現在のディレクトリにある実行可能ファイルを実行するには
./
を前につける必要があります。これは、セキュリティ上の理由から、現在のディレクトリがデフォルトの実行パスに含まれていないためです。
どちらのOSでも、コマンドを実行すると、ターミナルに以下の出力が表示されるはずです。
text
Hello, world!
おめでとうございます!Rustを使った初めてのプログラム作成、コンパイル、実行に成功しました!
手動での手順は、コンパイラがどのように機能するかを理解する上で役立ちますが、実際のRustプロジェクトでは、通常この方法は使いません。次に、Rustの標準的なビルドツールであるCargoを使った方法を見ていきましょう。
第5部: 「Hello, world!」プログラムの作成と実行 (Cargo)
現実世界のRustプロジェクトは、多くの場合複数のファイルから成り、外部のライブラリ(依存クレートと呼ばれます)を利用します。このような複雑なプロジェクトを効率的に管理するために、Rustのエコシステムには cargo
という強力なツールが標準で提供されています。Cargoは以下の役割を担います。
- プロジェクト管理: プロジェクトの構造を定義し、設定を管理します。
- ビルドシステム: ソースコードをコンパイルし、実行可能ファイルやライブラリを生成します。
- 依存クレート管理: プロジェクトが必要とする外部ライブラリをダウンロード、ビルドし、リンクします。
- テスト実行: プロジェクトに含まれるテストコードを実行します。
- ベンチマーク実行: コードのパフォーマンスを測定します。
- ドキュメント生成: コードからドキュメントを生成します。
Cargoを使うことで、プロジェクトのセットアップ、ビルド、依存関係の管理が劇的に簡単になります。Rustでの開発は、ほぼ常にCargoを使って行われます。
5.1. Cargoで新しいプロジェクトを作成
ターミナルまたはコマンドプロンプトで、手動で作成したディレクトリとは別の場所(または、手動で作成したディレクトリから出て、親ディレクトリなど)に移動し、以下のコマンドを実行します。
bash
cargo new hello_world_cargo
このコマンドは、hello_world_cargo
という名前の新しいディレクトリを作成し、その中に基本的なRustプロジェクトのスケルトンを自動で生成します。
コマンドを実行すると、以下のような出力が表示されるはずです。
text
Created binary (application) `hello_world_cargo` package
5.2. 生成されたプロジェクト構造を確認
cargo new
コマンドによって作成された hello_world_cargo
ディレクトリの中身を見てみましょう。
text
hello_world_cargo/
├── Cargo.toml
└── src/
└── main.rs
Cargo.toml
: これはCargoの設定ファイルです。プロジェクト名、バージョン、作者情報、そして依存クレート(使用する外部ライブラリ)などが記述されます。Rustプロジェクトにおいて、このファイルは非常に重要です。src/
: このディレクトリの中に、プロジェクトのソースコードを置きます。src/main.rs
:cargo new
はデフォルトでシンプルな「Hello, world!」プログラムが含まれたmain.rs
ファイルを生成してくれます。
Cargo.toml
ファイルの内容を見てみましょう。テキストエディタで開くと、以下のような内容が確認できます(バージョンや作者情報は異なる場合があります)。
“`toml
[package]
name = “hello_world_cargo”
version = “0.1.0”
edition = “2021”
See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
“`
[package]
: プロジェクト(クレートと呼ばれます)に関する設定セクションです。name
はプロジェクト名、version
はバージョン番号、edition
は使用するRustのエディション(言語のバージョンセットのようなもの)を示します。[dependencies]
: このセクションに、プロジェクトが依存する外部ライブラリをリストします。現時点では「Hello, world!」プログラムは外部ライブラリを使わないため、このセクションは空です。
次に、src/main.rs
ファイルを見てみましょう。
rust
fn main() {
println!("Hello, world!");
}
驚くことではないでしょう。手動で作成したものと全く同じコードです。Cargoは実行可能プログラム(バイナリ)を作成するプロジェクトのスケルトンとして、この標準的な「Hello, world!」コードを自動生成してくれるのです。
5.3. Cargoでプロジェクトをビルド
Cargoを使ってプロジェクトをビルド(コンパイル)するには、プロジェクトのルートディレクトリ(Cargo.toml
ファイルがあるディレクトリ)にいる状態で、以下のコマンドを実行します。
bash
cargo build
このコマンドを実行すると、Cargoは Cargo.toml
ファイルを読み込み、プロジェクトの設定や依存関係を解決し、src
ディレクトリ内のソースコードをコンパイルします。
初めてビルドする場合や、コードに変更を加えた場合は、コンパイルに少し時間がかかることがあります。Cargoはコンパイルの進行状況を表示します。
text
Compiling hello_world_cargo v0.1.0 (file:///path/to/your/project/hello_world_cargo)
Finished dev [unoptimized + debuginfo] target(s) in X.XXs
ビルドが成功すると、Finished dev [...]
のようなメッセージが表示されます。
cargo build
コマンドは、コンパイル済みの実行可能ファイルを target/debug/
ディレクトリ内に生成します。
text
hello_world_cargo/
├── Cargo.toml
├── src/
│ └── main.rs
└── target/
└── debug/
├── build/
├── deps/
├── hello_world_cargo (or hello_world_cargo.exe on Windows)
└── incremental/
target/debug/
ディレクトリは、開発中に使用されるデバッグビルドの出力先です。デバッグビルドは、デバッグ情報が含まれており、最適化は控えめになっています。本番環境で使用するリリースビルドを作成するには、cargo build --release
コマンドを使用します。この場合、出力は target/release/
ディレクトリに生成され、ファイルサイズは大きくなる傾向がありますが、高度な最適化が行われているため実行速度は速くなります。しかし、今回の「Hello, world!」のような単純なプログラムでは、その違いはほとんど体感できません。
5.4. Cargoでプロジェクトを実行
Cargoを使ってプロジェクトをビルドし、さらに実行するには、以下のコマンドを使います。
bash
cargo run
このコマンドは、まずコードに変更があれば自動的にビルドを実行し(ビルド済みの場合はスキップされます)、その後、生成された実行可能ファイルを自動的に実行してくれます。
text
Compiling hello_world_cargo v0.1.0 (file:///path/to/your/project/hello_world_cargo)
Finished dev [unoptimized + debuginfo] target(s) in X.XXs
Running `target/debug/hello_world_cargo`
Hello, world!
ビルドが不要な場合はコンパイルのステップはスキップされ、直接実行されます。
text
Running `target/debug/hello_world_cargo`
Hello, world!
出力として Hello, world!
が表示されれば成功です!
Cargoを使うことで、手動でのコンパイル・実行の手順が cargo run
という単一のコマンドに集約され、非常に効率的であることがわかるでしょう。実際のRust開発では、ほぼ常に cargo
コマンド(cargo build
, cargo run
, cargo test
, cargo update
, cargo publish
など)を使用して作業を進めます。
第6部: 「Hello, world!」コードの詳細解説
手動でもCargoでも同じコードを使用しました。ここで、改めてこのたった2行のコードについて、さらに詳しく掘り下げてみましょう。
rust
fn main() {
println!("Hello, world!");
}
6.1. fn main()
fn
キーワード: これは “function”(関数)を定義するためのキーワードです。Rustにおけるすべての関数定義はfn
で始まります。main
: これは関数の名前です。実行可能プログラムにおいて、main
という名前の関数は特別です。プログラムが起動されると、オペレーティングシステムはまずこのmain
関数を探し、そこからコードの実行を開始します。したがって、実行可能なRustプログラムには必ずfn main()
関数が必要です。()
: 関数の名前の後に続く括弧()
は、その関数が引数(入力値)を取るかどうかを示します。このmain
関数は引数を取らないため、括弧の中は空になっています。もし引数が必要な関数であれば、この中に引数の型と名前を記述します(例:fn add(x: i32, y: i32)
)。{}
: 関数の名前と引数の後には、波括弧{}
で囲まれたブロックが続きます。このブロックが関数の「本体」であり、関数が呼び出されたときに実行されるコードを含みます。波括弧で囲まれたコードの集合は「ブロック式」とも呼ばれ、文(statement)や式(expression)の並びで構成されます。Rustでは、波括弧{}
は単に関数の本体だけでなく、制御フロー構造(if文、ループなど)や、スコープを区切るためにも使用されます。
まとめると、fn main() { ... }
は、「プログラムの開始点となる main
という名前の、引数を取らない関数を定義します」という意味になります。
6.2. println!("Hello, world!");
これはこのプログラムの核心部分、つまり画面にテキストを出力する部分です。
println!
: これが実際に画面出力を行う命令です。末尾に!
が付いていることに注目してください。Rustにおいて、末尾に!
が付いている名前は「マクロ」であることを示します。- 関数 vs マクロ: 関数は実行時に呼び出される通常のサブルーチンですが、マクロはコンパイル時にコードを生成する仕組みです。マクロは、可変長引数を扱えたり、特定のパターンに基づいてコードを生成したり、ドメイン固有言語(DSL)のようなものを作成したりと、関数よりも柔軟で強力な機能を提供します。
println!
マクロは、与えられた引数(ここでは文字列"Hello, world!"
)を受け取り、それを標準出力(通常はターミナル)に表示するためのコードをコンパイル時に生成します。関数として実装することも不可能ではありませんが、マクロを使うことで、様々な型の引数を受け取ったり、コンパイル時に書式設定をチェックしたりといったメリットが得られます。 println!
マクロは、Rustの標準ライブラリ (std
) のio
モジュールの一部として提供されています。println!
は出力の最後に改行(newline)を追加します。改行なしで出力したい場合はprint!
マクロを使用します。
- 関数 vs マクロ: 関数は実行時に呼び出される通常のサブルーチンですが、マクロはコンパイル時にコードを生成する仕組みです。マクロは、可変長引数を扱えたり、特定のパターンに基づいてコードを生成したり、ドメイン固有言語(DSL)のようなものを作成したりと、関数よりも柔軟で強力な機能を提供します。
("Hello, world!")
: これはprintln!
マクロに渡される引数です。この場合、引数は()
で囲まれており、その中に"Hello, world!"
という文字列が記述されています。- 文字列リテラル:
"Hello, world!"
のように、二重引用符 ("
) で囲まれたテキストは「文字列リテラル」と呼ばれます。これはプログラム中に直接書き込まれた固定の文字列データです。Rustの文字列にはいくつかの種類がありますが、二重引用符で囲まれた文字列リテラルは静的に確保されたメモリ領域に格納され、プログラムの実行中ずっと有効であることが保証されます。その型は&'static str
と呼ばれます。
- 文字列リテラル:
;
: 行の末尾にあるセミコロン;
は、この行が「文(statement)」であることを示し、その文の終わりを示します。Rustのコードは、基本的に「文」と「式(expression)」で構成されます。文は何かアクションを実行するもので、値を返しません(または、Unit型()
と呼ばれる特殊な値を返します)。式の評価は常に何らかの値を生成します。println!
マクロの呼び出しはアクション(画面への出力)を実行するため、文として扱われ、末尾にセミコロンが必要です。関数の本体は、文の並びと、最後に評価される式(省略可能)で構成されます。main
関数のように、値を返さない(またはUnit型()
を返す)関数の場合、本体の最後の式にもセミコロンをつけるのが慣習です。
したがって、println!("Hello, world!");
は、「println!
マクロを呼び出し、引数として文字列リテラル "Hello, world!"
を渡し、標準出力にその文字列と改行を表示しなさい。これは一つの文として扱います。」という意味になります。
たった2行のコードですが、その背後には関数の概念、エントリポイント、マクロ、文字列リテラル、文と式の区別、そしてRustの基本的な文法が含まれています。
第7部: コンパイルと実行の仕組み (舞台裏)
「Hello, world!」プログラムは非常に単純ですが、ソースコードが書かれてから画面に文字が表示されるまでには、いくつかの重要なステップがあります。ここでは、そのプロセスを簡単に見てみましょう。
- ソースコード (.rs ファイル): あなたがテキストエディタで記述したRustコードです。これは人間が読んで理解しやすいテキスト形式です。
- Rustコンパイラ (
rustc
):rustc main.rs
またはcargo build
コマンドを実行すると、Rustコンパイラが起動します。- 字句解析 (Lexing): コンパイラはソースコードのテキストを読み込み、単語(トークン、例えば
fn
,main
,println!
,"Hello, world!"
,;
,{
,}
など)に分割します。 - 構文解析 (Parsing): トークンの並びがRustの文法規則に従っているかをチェックし、コードの構造を表現する「抽象構文木 (Abstract Syntax Tree – AST)」を生成します。
- 意味解析 (Semantic Analysis) / 型チェック / 借用チェック: ASTを使って、コードの意味を解釈します。変数や関数の定義と使用が一致しているか、型の互換性があるか、そしてRust独自の所有権と借用の規則が守られているかを厳密にチェックします。Rustコンパイラの有名な「Borrow Checker(借用チェッカー)」はここで機能します。ここでエラーが見つかると、コンパイルは中断され、親切なエラーメッセージが表示されます。メモリ安全性やスレッド安全性の保証は、主にこの段階で行われます。
- 中間表現 (Intermediate Representation – IR): チェックが完了し、コードが正当であることが確認されると、コンパイラはコードをより抽象的な中間表現に変換します。Rustコンパイラは通常、いくつかの内部的な中間表現(例えばMIR: Mid-level Internal Representation)を経由し、最終的にLLVM (Low Level Virtual Machine)という広く使われているコンパイラ基盤のIRに変換します。
- コード生成と最適化: LLVMは、このIRをターゲットとするコンピュータのアーキテクチャ(x86_64, ARMなど)に合わせた機械語に変換します。この過程で、パフォーマンス向上のための様々な最適化(不要なコードの削除、処理順序の変更など)が行われます。
- リンカー (Linker): コンパイラが生成した機械語コードは、そのままでは単独で実行できるとは限りません。プログラムが使用する標準ライブラリの関数(例えば、
println!
マクロが内部で使用するOSレベルの画面出力機能など)や、もしあれば依存している外部ライブラリのコードと結合(リンク)される必要があります。この結合を行うのがリンカーです。Rustコンパイラは内部でシステムにインストールされているリンカー(例えば、Linuxのld
、macOSのld
、WindowsのMSVCリンカーなど)を呼び出します。 - 実行可能ファイル: リンカーによってすべての必要なコードが結合されると、最終的にオペレーティングシステムが直接実行できる形式のファイルが生成されます(Windowsでは
.exe
、Linux/macOSでは拡張子なしのバイナリファイル)。 - オペレーティングシステム (OS): ターミナルから実行可能ファイル名を入力してEnterキーを押すと、OSは以下の処理を行います。
- 指定されたファイルを探します。
- ファイルが実行可能ファイルであることを確認します。
- ファイルをメモリに読み込みます。
- 新しい「プロセス」を生成し、そのプロセス内でプログラムの実行を開始します。
- プログラムのエントリポイント、つまり
fn main()
関数を見つけ、そこから命令の実行を開始します。
- プログラムの実行:
main
関数内のコードが順番に実行されます。今回の場合は、println!("Hello, world!");
マクロが評価され、その結果として"Hello, world!"
という文字列がOSに渡され、OSがそれを標準出力(多くの場合、あなたがコマンドを入力したターミナル画面)に表示します。 - プログラムの終了:
main
関数の最後に到達すると、プログラムの実行は終了し、OSに制御が戻ります。
このプロセス全体を通して、Rustコンパイラは非常に厳密なチェックを行います。特に所有権システムによるチェックは、コンパイル時に多くの潜在的なバグを発見するため、実行時エラーやセキュリティ脆弱性を減らすのに大いに役立ちます。これが「コンパイルが通ればだいたい大丈夫」とRustコミュニティで言われる理由の一つです。
第8部: なぜ「Hello, world!」から始めるのか?
ほとんど全てのプログラミング言語の入門ガイドが「Hello, world!」から始まるのには理由があります。
- 環境セットアップの確認: 「Hello, world!」を成功させることは、プログラミング言語のコンパイラ(またはインタプリタ)や関連ツールが正しくインストールされ、システム上で利用できる状態になっていることを確認する最も簡単な方法です。コンパイルや実行ができない場合、多くは環境設定に問題があることを示しています。
- 基本的なワークフローの体験: ソースコードを作成し、保存し、コンパイルし、実行するという、プログラミングにおける最も基本的な開発ワークフローを体験できます。
- 最小限の構文に触れる: 「Hello, world!」プログラムは、言語の基本的な構文要素(Rustの場合は関数定義、マクロ呼び出し、文字列リテラル、文末のセミコロンなど)に触れる機会を提供します。
- 成功体験: プログラムが期待通りに動作し、「Hello, world!」と表示されることは、プログラミング学習の最初の一歩として大きな成功体験となり、学習へのモチベーションを高めます。
Rustの「Hello, world!」は特に、fn main()
, println!
, ;
といったRust特有の基本的な構文要素に触れる良い機会となります。そして、手動での rustc
の使い方と、より実践的な cargo
の使い方という、Rust開発における2つの主要なワークフローを体験できます。
第9部: トラブルシューティング (よくある問題)
Rustのインストールや「Hello, world!」の実行中に、いくつかの問題に遭遇する可能性があります。ここでは、よくある問題とその解決策をいくつか紹介します。
-
command not found: rustc
またはcommand not found: cargo
- 原因: Rustツールチェインが正しくインストールされていないか、インストールされているディレクトリがシステムの
PATH
環境変数に追加されていないため、ターミナルがrustc
やcargo
コマンドを見つけられない。 - 解決策:
- Rustが正しくインストールされたか、
rustup --version
コマンドで確認してください。 - インストール後にターミナル/コマンドプロンプトを再起動しましたか?多くのOSでは、新しい環境変数を読み込むためにシェルを再起動する必要があります。
- macOS/Linuxの場合、インストール完了時に表示された
source $HOME/.cargo/env
を実行したか確認してください。または、~/.bashrc
,~/.zshrc
などのシェルの設定ファイルに$HOME/.cargo/bin
がPATHに追加されているか確認してください。 - Windowsの場合、システム環境変数のPATHに
%USERPROFILE%\.cargo\bin
が追加されているか確認してください。 - インストール自体に失敗した場合は、
rustup self uninstall
で一度Rustをアンインストールしてから、再度インストールを試みてください。
- Rustが正しくインストールされたか、
- 原因: Rustツールチェインが正しくインストールされていないか、インストールされているディレクトリがシステムの
-
コンパイルエラー: コードをコンパイルしたときに、
rustc
がエラーメッセージを表示して停止する。- 原因: ソースコードに文法的な誤りや、Rustの型システム、所有権システムに関する誤りがある。
- 解決策:
- エラーメッセージをよく読んでください。Rustコンパイラのエラーメッセージは非常に親切で、問題の箇所(ファイル名、行番号、列番号)と、何が問題なのか、そしてしばしばどうすれば解決できるのかというヒントを示してくれます。
- 特に初心者によくあるのは、タイポ(スペルミス)、セミコロン
;
の忘れ、波括弧{}
や丸括弧()
の対応関係の間違いです。手動で入力した場合、fn
,main
,println
,!
,"
,;
,{
,}
などの文字が正確かダブルチェックしてください。 - コピー&ペーストした場合は、隠れた文字が入っていないか確認したり、手打ちで再入力してみるのも良い方法です。
-
実行時エラー (手動コンパイルの場合): コンパイルは成功したが、生成された実行可能ファイルを実行しようとするとエラーになる。
- 原因:
- Windows以外で
./
を付けずに実行しようとした (main
とだけ入力した)。 - ファイル名またはパスが間違っている。
- 実行ファイルが作成されていない(コンパイルが実は成功していなかった)。
- Windows以外で
- 解決策:
- macOS/Linuxでは、必ず
./
を付けて./main
のように実行してください。 - Windowsでは、
main.exe
またはmain
で実行できます。 - コンパイルコマンド (
rustc main.rs
) を実行したディレクトリと、実行コマンド (./main
やmain.exe
) を実行するディレクトリが同じであることを確認してください。ls
(Linux/macOS) またはdir
(Windows) コマンドで、コンパイル後に実行可能ファイル (main
またはmain.exe
) が生成されているか確認してください。
- macOS/Linuxでは、必ず
- 原因:
-
WindowsでのVisual Studio Build Tools関連のエラー:
rustup-init.exe
実行後やcargo build
実行時に、Visual Studio Build Toolsやリンカーが見つからないといったエラーが発生する。- 原因: Rustが依存するC/C++のビルドツール(リンカーなど)がシステムにインストールされていない。
- 解決策: Microsoftの公式サイトからVisual Studio Community版をダウンロード&インストールするか、Visual Studio Build Tools単体をダウンロード&インストールしてください。インストール時には「C++によるデスクトップ開発」または少なくとも「C++ Build Tools」を選択して必要なコンポーネントをインストールする必要があります。インストール完了後、Rust関連のコマンドを再試行してください。
もし上記以外の問題に遭遇した場合は、エラーメッセージをコピーしてウェブ検索するのが最も効果的な解決策です。Rustのエラーメッセージは検索しやすいように設計されています。Stack OverflowやRustの公式フォーラムなど、活発なコミュニティも問題解決の手助けをしてくれるでしょう。
第10部: 「Hello, world!」の次へ
「Hello, world!」のプログラムを無事に実行できたあなたは、Rustプログラミングの最初の、そして最も重要な一歩を踏み出しました。しかし、これはまだ旅の始まりに過ぎません。Rustには学ぶべき興味深く、そして強力な概念がたくさんあります。
「Hello, world!」の次に学ぶべき、いくつかの重要なトピックを簡単に紹介します。
- 変数と可変性: 値を保持するための変数を宣言し、その値が変更可能か不可能かを制御する方法を学びます(Rustではデフォルトで変数は不変です)。
- 基本的なデータ型: 整数、浮動小数点数、真偽値、文字、文字列、タプル、配列といったRustのプリミティブ型について理解します。
- 関数:
main
関数以外の独自の関数を定義し、引数を渡し、値を返す方法を学びます。 - コメント: コード中に説明を記述し、コンパイラに無視させる方法を学びます。
- 制御フロー: 条件分岐(
if
,else if
,else
)や繰り返し(loop
,while
,for
)を使って、プログラムの実行の流れを制御する方法を学びます。 - 所有権システム: Rustの最も独特で強力な機能である「所有権(Ownership)」、「借用(Borrowing)」、「ライフタイム(Lifetimes)」といった概念を深く理解します。これがRustのメモリ安全性保証の根幹です。これは少し難しいかもしれませんが、時間をかけて学ぶ価値は十分にあります。
- 構造体と列挙型: 複数の関連するデータをまとめる構造体(struct)や、取りうる値が限定されている場合に便利な列挙型(enum)を定義する方法を学びます。
- マッチング: 値のパターンに基づいてコードを実行する強力な
match
式を学びます。 - モジュールとクレート: コードを整理し、複数のファイルやディレクトリに分割する方法、そして他の人が書いたコード(クレート)を利用する方法を学びます。Cargoの依存関係管理機能がここで活きてきます。
- エラーハンドリング: Rustが推奨する堅牢なエラー処理の方法(
Result
型、Option
型、panic!
マクロなど)を学びます。
これらのトピックを学ぶための最も推奨されるリソースは、Rustの公式ドキュメント「The Rust Programming Language」(通称「The Book」)です。ウェブサイト https://doc.rust-lang.org/book/ で無料で読むことができ、多くの言語で翻訳版も提供されています。この本は初心者向けに非常に分かりやすく書かれており、「Hello, world!」の次に何を学ぶべきかを明確に示してくれます。
Cargoを使ったプロジェクトの作成と実行の方法を学んだあなたは、すでに「The Book」や他のチュートリアルを進めるための基本的なスキルセットを持っています。新しい概念を学びながら、小さなプログラムを実際に書いて、コンパイルし、実行するというサイクルを何度も繰り返すことが、上達への一番の近道です。
第11部: まとめと次のステップへの激励
この詳細なガイドを通じて、あなたはRust開発環境のセットアップから始まり、手動およびCargoを使った「Hello, world!」プログラムの作成と実行を体験し、さらにそのコードと実行プロセスの背後にある仕組みについて深く理解を深めました。
あなたは Rust コンパイラ (rustc
) とビルドシステム/パッケージマネージャー (cargo
) という Rust 開発における主要なツールを使いこなすための最初のステップを踏み出しました。特に cargo
は今後の Rust プロジェクト開発において非常に重要な役割を果たします。
「Hello, world!」はどんなプログラミング言語にとっても象徴的なスタート地点です。この小さな成功は、これからあなたがRustでより複雑で挑戦的なプログラムを作成していくための自信につながるはずです。
Rustは、その独自の概念(特に所有権システム)のために、最初のうちは難しく感じられるかもしれません。コンパイラが厳格であるため、慣れるまではコンパイルエラーに頻繁に遭遇する可能性があります。しかし、これはRustがあなたのコードを安全かつ効率的にするために助けてくれているのだと考えてください。コンパイラのエラーメッセージはあなたの先生です。エラーメッセージをよく読み、理解しようと努めることが、Rustの考え方を習得する鍵となります。
恐れずに様々なコードを試し、エラーから学び、公式ドキュメントやコミュニティのリソースを活用してください。Rustの学習曲線は、最初は急峻かもしれませんが、その先には強力で信頼性の高いソフトウェアを構築できるという大きな報酬が待っています。
あなたのRustプログラミングの旅は始まったばかりです。このガイドが、その旅の良い出発点となったことを願っています。さあ、次に進んで、変数、関数、そしてRustの最もエキサイティングな機能である所有権について学び始めましょう。
頑張ってください、そしてRustでのコーディングを楽しんでください!
[記事の終わり]