定期的に新しいことを初めてすぐに止まることが多いが、めげずに進める。 底本はThe Rust Programming Language 2nd editionである。 なお、自分のための記録であるため、原著の要約を期待して読むとがっかりすると思われる。
はじめに(Introduction)
- Rustは安全性、速度、並列性に焦点を当てている。
- Rustは低レベル言語のような性能と制御、高レベル言語のような高度な抽象性をプログラムがもつようにデザインされている。
- Cのような言語の経験者やより安全なものを探している人、Pythonのような言語の経験者で表現性を犠牲にせずにより良い性能を出したい人に向いている。
- 安全性のチェックやメモリ管理はコンパイル時に行うので実行時の性能に影響を与えない。他の言語ではうまくいかない多くのユースケース(計算時間とメモリ使用量が予測可能なプログラム、他の言語への埋め込み、デバイスドライバやオペレーティングシステムなどの低レベルコードの作成)役に立つ。Webアプリケーションにも向いている。
- 『The Rust Programming Language』は少なくとも1つの言語でプログラミングをする方法を知っている読者を対象にしている。
よくある読者のやる気を高める宣伝文。一応、今はPythonのプログラムを書くことで生活しているので「少なくとも1つの言語でプログラミングをする方法を知っている読者」とみなしてよいだろう。
インストール(Installation)
Windowsにおけるインストール(Installing on Windows)
Windowsの場合はインストーラーを叩くだけの簡単なお仕事...と思っていたら「Visual C++ 2015 Build Tools」を要求された。 インストーラの指示に従ってインストールする。 デフォルトだとログインしているユーザーのホームディレクトリにインストールされるようである。
$ rustc --version rustc 1.24.0 (4d90ac38c 2018-02-12)
Rustプログラムの記述と実行(Writing and Running a Rust Program)
- ファイル名は
main.rs
。Rustファイルの拡張子は常に.rs
。ファイル名はアンダースコアで区切る。
エディタはひとまずVisual Studio Codeを利用する。IDEがない場合は大抵VS Codeを選択することが多い。
fn main() { println!("Hello, world!"); }
rustc
でコンパイルする。
$ rustc main.rs $ main.exe Hello, world!
VC++ランタイムが必要であったとはいえ、同じソースコードでOSに関係なくビルドできるのは便利である。 公式ドキュメント曰く、これで公式のRustプログラムを書いたことになり、Rustプログラマになったのである。 私はRustプログラマである。
Rsutプログラムの解剖学(Anatomy of a Rust Program)
fn main() { }
println!("Hello, world!");
- インデントは4スペースであり、タブではない。
println!
はRustのマクロと呼ばれるもの。Rustでメタプログラミングを実現している。詳細はAppendix Dで扱い、ひとまず!
がマクロであることを押さえておく。- 行末は
;
で終える。
なお、println!
とせずprintln
とするとコンパイルエラーとなる。
error[E0423]: expected function, found macro `println` --> src\main.rs:2:5 | 2 | println("Hello, world!"); | ^^^^^^^ did you mean `println!(...)`? error: aborting due to previous error error: Could not compile `hello_cargo`.
println
がありません、ではなくprintln!
じゃないですか、とエラーメッセージを送ってくれるのはちょっとうれしい。
Hello worldの伝統から最初にI/Oをやるのだが、プログラムにおいてI/Oって結構特殊な部類なのでは、と思ったりもする。
コンパイルと実行は別々のステップである(Compiling and Running Are Separate Steps)
Hello, Cargo!
- CargoはRustのビルドツール、パッケージマネージャー。コードのビルド、依存ライブラリのダウンロードとライブラリのビルドを行う。
$ cargo --version cargo 0.25.0 (8c93e0895 2018-02-01)
Cargoで新規にプロジェクトを作成するには cargo new hello_cargo --bin
と打つ。
--bin
オプションは実行バイナリを作るためのものである。デフォルトはライブラリとなる。
$ cargo new -h Create a new cargo package at <path> Usage: cargo new [options] <path> cargo new -h | --help Options: -h, --help Print this message --vcs VCS Initialize a new repository for the given version control system (git, hg, pijul, or fossil) or do not initialize any version control at all (none), overriding a global configuration. --bin Use a binary (application) template --lib Use a library template [default] --name NAME Set the resulting package name, defaults to the value of <path> -v, --verbose ... Use verbose output (-vv very verbose/build.rs output) -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never --frozen Require Cargo.lock and cache are up to date --locked Require Cargo.lock is up to date -Z FLAG ... Unstable (nightly-only) flags to Cargo
Cargoは設定ファイルCargo.toml
、ソースコードディレクトリsrc
とmain.rs
、そして.gitignore
を生成する。git
以外のバージョン管理ツールを使う場合は--vcs
で指定する。
構造としては以下の通りとなる。
│ .gitignore │ Cargo.toml │ └─src main.rs
ビルドはcargo build
、実行するにはcargo run
、リリース用のビルドはcargo build --release
とする。
実際に実行すると大量のファイルが生成される。
.gitignore │ Cargo.lock │ Cargo.toml │ ├─src │ main.rs │ └─target ├─debug │ │ .cargo-lock │ │ hello_cargo.d │ │ hello_cargo.exe │ │ │ ├─.fingerprint │ │ └─hello_cargo-c909bb4d8770b1a8 │ │ bin-hello_cargo-c909bb4d8770b1a8 │ │ bin-hello_cargo-c909bb4d8770b1a8.json │ │ dep-bin-hello_cargo-c909bb4d8770b1a8 │ │ │ ├─build │ ├─deps │ │ hello_cargo-c909bb4d8770b1a8.d │ │ hello_cargo-c909bb4d8770b1a8.exe │ │ hello_cargo-c909bb4d8770b1a8.pdb │ │ │ ├─examples │ ├─incremental │ │ └─hello_cargo-3lmpxjy8e6kta │ │ │ s-eyo5s02mrc-1wwhhsl.lock │ │ │ │ │ └─s-eyo5s02mrc-1wwhhsl-3ewijj0am31b3 │ │ 1y16o1qfye96o7m0.o │ │ 3rngp6bm2u2q5z0y.o │ │ 4xq48u46a1pwiqn7.o │ │ dep-graph.bin │ │ f80e96b5kob4hc2.o │ │ query-cache.bin │ │ work-products.bin │ │ │ └─native └─release │ .cargo-lock │ hello_cargo.d │ hello_cargo.exe │ ├─.fingerprint │ └─hello_cargo-c9cb027cd6477672 │ bin-hello_cargo-c9cb027cd6477672 │ bin-hello_cargo-c9cb027cd6477672.json │ dep-bin-hello_cargo-c9cb027cd6477672 │ ├─build ├─deps │ hello_cargo-c9cb027cd6477672.d │ hello_cargo-c9cb027cd6477672.exe │ hello_cargo-c9cb027cd6477672.pdb │ ├─examples ├─incremental └─native
Cargoによる実行も--release
フラグで開発バイナリと本番バイナリを選択することができる。
$ cargo run --release Finished release [optimized] target(s) in 0.0 secs Running `target\release\hello_cargo.exe` Hello, world!
$ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running `target\debug\hello_cargo.exe` Hello, world!
rustc
でコンパイルした時とは出力結果がだいぶ異なるが、その秘密は--verbose
フラグを付けるとわかる。
$ cargo build --verbose Compiling hello_cargo v0.1.0 (file:///C:/Users/hayao/Documents/rust_projects/hello_cargo) Running `rustc --crate-name hello_cargo src\main.rs --crate-type bin --emit=dep-info,link -C debuginfo=2 -C metadata=c909bb4d8770b1a8 -C extra-filename=-c909bb4d8770b1a8 --out-dir C:\Users\hayao\Documents\rust_projects\hello_cargo\target\debug\deps -C incremental=target\debug\incremental -L dependency=target\debug\deps` Finished dev [unoptimized + debuginfo] target(s) in 0.98 secs
$ cargo build --release --verbose Compiling hello_cargo v0.1.0 (file:///C:/Users/hayao/Documents/rust_projects/hello_cargo) Running `rustc --crate-name hello_cargo src\main.rs --crate-type bin --emit=dep-info,link -C opt-level=3 -C metadata=c9cb027cd6477672 -C extra-filename=-c9cb027cd6477672 --out-dir target\release\deps -L dependency=target\release\deps` Finished release [optimized] target(s) in 0.69 secs
デバッグビルドではデバッグフラグ、本番ビルドでは最適化フラグが立っていることがわかる。
公式でビルドツールが用意されていると安心感がある。
昔、Javaを触っていた時はMavenであった。
Pythonはpip
が後から公式ツールとなった。
1章はRustの宣伝とコンパイラとビルドツールの基本的な使い方の説明で特に困ることはない。 2章ではHello worldよりもずっと複雑なプログラムを行っていく。