---
# System prepended metadata

title: about the Rust

---

# about the Rust

この document の方向性。

> 言語コンセプトですね。
> 簡単に言えば、この言語を使うと何が嬉しいんだっけ？というやつです。

## この document の reference ではなく、読み物としての link 集

- [The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/)
- [DRY - Rust を始めるための資料集](https://blog-dry.com/entry/2021/01/23/141936)
- [Zenn - Rust 入門](https://zenn.dev/mebiusbox/books/22d4c1ed9b0003)
- [Zenn - RustCoder AtCoder と Rust で始める競技プログラミング入門](https://zenn.dev/toga/books/rust-atcoder)
- [Zenn - Rust は何を解決しようとしたのか; メモリとリソースと所有権](https://zenn.dev/karno/articles/630a64fbc9c65e29b566)
- [いもす研 - Rust は何が新しいのか（基本的な言語機能の紹介）](https://imoz.jp/note/rust-functions.html)

## Rust の特徴や pros

### Package 周り

- `rustup`
  - Rust のツールチェーン
    - Rust コンパイラ (`rustc`) や language server などを install するときに使う
- `cargo`
  - Package マネージャー / build tool

---

- 基本的に `rustup` は最初の install 時のみ使う。基本的な作業としては `cargo` を使う
- `cargo` 自体は binary
- コンパイラと同じ母体が開発しているためグダグダにならない (pip とか npm / yarn みたいなことがない)
  - パッケージレジストリも今の所唯一 (crates.io)
- 最近の他言語の Package マネージャー / build tool がやれることは大体できる
  - セマンティックバージョニングで依存関係を管理
  - git からのソースを取得
  - 依存関係のプロジェクト毎の隔離
    - not Python pip
  - lock ファイルでの再現性のあるビルド
  - 設定を殆ど書かなくて良い
  - ライブラリとバイナリの両方を扱える
  - テスト用などの開発時専用の依存関係を書ける
- 面倒を見る範囲が広い
  - スケルトン生成 (`cargo new`)
  - エラーチェック (`cargo check`)
  - ビルド (`cargo build`)
  - 実行 (`cargo run`)
  - テスト (`cargo test`)
  - ドキュメント生成 (`cargo doc`)
  - パッケージの release (`cargo publish`)
  - パッケージバイナリのインストール (`cargo install`)
- formatter としては、`rust-lang/rustfmt` という同じ母体のデファクトツールが有る

### Documentation comment

- `///` や `//!` といった通常のコメント (`//`) とことなる特殊なコメントを書ける
- `cargo doc` で HTML 形式のドキュメントを自動生成できる
- コメント内で markdown が書ける
- コメント内に test code が書けて実行できる
- すべて言語組み込みとして実装されている

### Test

- 言語組み込みでテストモジュールが含まれている `cargo test`
- 単体テストは基本的に同ファイル内に書く
- もっと上の layer のテストは `tests` directory に書く
- test library としての基本的な機能は大体揃っている
- `cargo bench` というベンチマーク用のコマンドもある

### Build

- `cargo build` で library や binary を生成する
- `cargo build --target` でクロスコンパイルできる
  - libc とかに静的リンクした binary がほしければ、`x86_64-unknown-linux-musl` を target にすれば良い
  - Docker の scratch image とかに、そのまま binary を add して動かせる

```bash
$ rustup target list | pr -w 90 --column=3

aarch64-apple-darwin	      i586-unknown-linux-musl	    thumbv6m-none-eabi
aarch64-apple-ios	      i686-linux-android	    thumbv7em-none-eabi
aarch64-fuchsia		      i686-pc-windows-gnu	    thumbv7em-none-eabihf
aarch64-linux-android	      i686-pc-windows-msvc	    thumbv7m-none-eabi
aarch64-pc-windows-msvc	      i686-unknown-freebsd	    thumbv7neon-linux-androideabi
aarch64-unknown-linux-gnu     i686-unknown-linux-gnu	    thumbv7neon-unknown-linux-gnu
aarch64-unknown-linux-musl    i686-unknown-linux-musl	    thumbv8m.base-none-eabi
aarch64-unknown-none	      mips-unknown-linux-gnu	    thumbv8m.main-none-eabi
aarch64-unknown-none-softfloa mips-unknown-linux-musl	    thumbv8m.main-none-eabihf
arm-linux-androideabi	      mips64-unknown-linux-gnuabi64 wasm32-unknown-emscripten
arm-unknown-linux-gnueabi     mips64-unknown-linux-muslabi6 wasm32-unknown-unknown
arm-unknown-linux-gnueabihf   mips64el-unknown-linux-gnuabi wasm32-wasi
arm-unknown-linux-musleabi    mips64el-unknown-linux-muslab x86_64-apple-darwin
arm-unknown-linux-musleabihf  mipsel-unknown-linux-gnu	    x86_64-apple-ios
armebv7r-none-eabi	      mipsel-unknown-linux-musl	    x86_64-fortanix-unknown-sgx
armebv7r-none-eabihf	      nvptx64-nvidia-cuda	    x86_64-fuchsia
armv5te-unknown-linux-gnueabi powerpc-unknown-linux-gnu	    x86_64-linux-android
armv5te-unknown-linux-musleab powerpc64-unknown-linux-gnu   x86_64-pc-windows-gnu
armv7-linux-androideabi	      powerpc64le-unknown-linux-gnu x86_64-pc-windows-msvc
armv7-unknown-linux-gnueabi   riscv32i-unknown-none-elf	    x86_64-rumprun-netbsd
armv7-unknown-linux-gnueabihf riscv32imac-unknown-none-elf  x86_64-sun-solaris
armv7-unknown-linux-musleabi  riscv32imc-unknown-none-elf   x86_64-unknown-freebsd
armv7-unknown-linux-musleabih riscv64gc-unknown-linux-gnu   x86_64-unknown-illumos
armv7a-none-eabi	      riscv64gc-unknown-none-elf    x86_64-unknown-linux-gnu (ins
armv7r-none-eabi	      riscv64imac-unknown-none-elf  x86_64-unknown-linux-gnux32
armv7r-none-eabihf	      s390x-unknown-linux-gnu	    x86_64-unknown-linux-musl
asmjs-unknown-emscripten      sparc64-unknown-linux-gnu	    x86_64-unknown-netbsd
i586-pc-windows-msvc	      sparcv9-sun-solaris	    x86_64-unknown-redox
i586-unknown-linux-gn
```

### IDE

- vscode に `rust` という拡張を入れる
- language server や formatter と連携しつついい感じにやってくれる
- コンパイラによるエラーもコード上に表示してくれる
  - 基本的に Rust はコンパイラから怒られなければなんとかなる言語

### 後方互換性

- Edition という概念で後方互換性を維持している
- `Cargo.toml` という node.js でいう `package.json` みたいなファイルに `edition = 2018` のように書く
- 現在の edition は、2015 と 2018 のみ
- edition が違うからといって、別のコンパイラを使うみたいなことはない

### 言語仕様というか言語コンセプト

- 性能、メモリ安全性、安全な並行性を目指して設計されたマルチパラダイム言語
- GC なしでのメモリ安全性
  - 値と変数に所有権や lifetime という概念を導入して、コンパイル時にチェックする
- 表面上は手続き型、小さな単位でのコードの書き方は関数型 (あんまりゴリゴリのやつではなくイテレータとかラムダ式とかライトなやつ)
- 変数は基本的に immutable、可変変数を扱いたい場合は `mut` keyword を使う
- 基本的に「文」ではなく「式」 (e.g. if 式)
- 静的型付けかつ強い型付け
  - コンパイル時に全ての型を決定しなければならない
  - ただ、強い型推論があるため、変数の型を一々書くことはない
  - 型システムとしては impl、trait, struct, enum を基本として、Generics も使える
- 例外はない

### 例外処理

- 戻り値を使ってエラーハンドリングする (Go みたいに)
- 基本的に関数は `Result<T, E>` という Result 型 (enum) を返すように書く

```rust
enum Rusult<T, E> {
  Ok(T),
  Err(E)
```

- 厳密には match 式を使ってエラー処理を書いていく
- 回復不能なエラーとして `panic!` マクロが用意されている
  - 巻き戻してメモリの片付けなどして異常終了する

---

- 流石に全部独自 Error を定義したり、match 式で判定するのは面倒なため、色々なシンタックスシュガーが用意されている
  - `?` 演算子
    - 値が `Err` なら即座に return する (例外のようなもの)
  - `and_then` や `unwrap` のようなメソッド
  - `anyhow` や `thiserror` といった、抽象的なエラー型を集めたり生成するライブラリ

---

- ちなみに null も存在しない
  - `Option<T>` という Option 型 (enum) を使う

```rust
enum Option<T> {
    None,
    Some(T),
}
```

- Result も Option の両方ともちゃんと解決しない場合、コンパイラから怒られる

### 色々なライブラリ

- 乱数生成
  - rand
- 正規表現
  - regex
- 時刻操作
  - chrono
- ロギング
  - log
- json/yaml 周り
  - serde
    - 良く出来てる
- argument parser
  - clap
- web framework
  - https://github.com/flosse/rust-web-framework-comparison
  - actix_web ってのがデファクト
    - マルチスレッド化はちゃんと書かないといけない

### その他

- 時間がなかったもの
  - WebAssembly
  - 並列プログラミング (async / await)
  - Rust から C++ を呼ぶ
