about the Rust

この document の方向性。

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

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 して動かせる
$ 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) を返すように書く
enum Rusult<T, E> {
  Ok(T),
  Err(E)
  • 厳密には match 式を使ってエラー処理を書いていく
  • 回復不能なエラーとして panic! マクロが用意されている
    • 巻き戻してメモリの片付けなどして異常終了する

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

  • ちなみに null も存在しない
    • Option<T> という Option 型 (enum) を使う
enum Option<T> {
    None,
    Some(T),
}
  • Result も Option の両方ともちゃんと解決しない場合、コンパイラから怒られる

色々なライブラリ

  • 乱数生成
    • rand
  • 正規表現
    • regex
  • 時刻操作
    • chrono
  • ロギング
    • log
  • json/yaml 周り
    • serde
      • 良く出来てる
  • argument parser
    • clap
  • web framework

その他

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