Rust 入門

〜第1回〜

Rustとは

開発

  • 開始
    • 2006年
  • 初期開発者
    • Graydon Hoare
  • 正式プロジェクト開始
    • 2009年(Mozilla社にて)
  • 安定版リリース
    • 2015年
  • システムプログラミング言語
  • ゴール
    • ​速度、安全性、並行性

最も愛されている開発言語(2019年)

利用企業例

Hello, World!

Hello, Cargo!

Rust そのもののインストールはやらないよ

コンパイルと実行

fn main() {
    println!("Hello, world!");
}

1. main.rsを作成

2. コンパイルと実行

$ rustc main.rs
$ ./main
Hello, world!

自動フォーマッター

$ rustfmt --check main.rs
Diff in /Users/hironori/work/learn-rust-programming/hello_world/main.rs at line 1:
 fn main() {
- println!("Hello, world!");
+    println!("Hello, world!");
 }
 
 $ rustfmt main.rs
  • 空白を削除してみて --check オプションで変更されることを確認
  • 実際にフォーマット変更

Cargo

  • ビルドシステムおよびパッケージマネージャー
  • コードに依存関係が必要なライブラリを呼び出す

プロジェクトの作成

$ cargo new hello_cargo

TOMLファイル

$ cat Cargo.toml
[package]
name = "hello_cargo"
version = "0.1.0"
authors = ["hirontan <hirontan@sora.flights>"]
edition = "2018"

[dependencies]
  • package:ステートメント
    • 名前、バージョン、作成者、使用するエディションの記載
  • dependencies:プロジェクトの依存関係リスト
    • コードのパッケージはクレートと呼ばれる

Cargo について補足

  • ソースファイルがsrcディレクトリ内にある
  • 最上位のプロジェクトディレクトリは、READMEファイル、
    ライセンス情報、構成ファイル、およびコードに関係のないものである
  • Cargoを利用しないプロジェクトで始めた場合、
    ソースコードをsrcディレクトリに置き直し、TOMLファイルを作成する
$ tree
.
├── Cargo.lock
├── Cargo.toml
└── src
     └── main.rs

ビルドと実行

$ cargo build
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s

ビルド

  • target/debug/hello_cargo に実行ファイルができる
  • Cargo.lock ファイルができ、依存関係を記載してくれる

実行

$ ./target/debug/hello_cargo
Hello, world!

ワンコマンドで!

$ cargo run

おまけ

$ cargo build --release
  • target/release 配下にファイルが
    できる
  • 最適化によりコード実行が高速になる
    かわりに、コンパイルに時間がかかる
  • 実行時間のベンチマークをする場合、
    target/release の実行ファイルを
    実行する
$ cargo check

コンパイルのみ実行

リリース用ビルド

  • 実行ファイルは生成されない

Rustの特徴(一部)

3章までの話まで

変数のデフォルトがimmutable

// src/main.rs
fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}
$ cargo run
   Compiling variables v0.1.0
error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         -
  |         |
  |         first assignment to `x`
  |         help: make this binding mutable: `mut x`
3 |     println!("The value of x is: {}", x);
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0384`.
error: could not compile `variables`.

To learn more, run the command again with --verbose.

コード

実行

  • 不変変数x(immutable)に2回代入してはならない
  • コンパイル時にエラーが出る
  • 値の変化しない変数はわかるようになる

mutableにしたい場合、
let mut ​キーワードを利用する

ステートメントは値を返さない

  • letステートメントを別の変数に割り当てることはできません
  • CやRubyなどでは、x = y = 6 で x と y 両方に 6 を割り当てられるが、
    Rustは割り当てられない
fn main() {
    let x = (let y = 6); # → letステートメントで別の変数を割り当てている。Rustではエラーになる。
}

ブロック{}はletステートメントで扱える

fn main() {
    let y = {
        let x = 3;
        x + 1
    };
}
  • 最後の式を暗黙的に返す

戻り値を持つ関数は、-> の後に型を宣言

fn main() {
    plus_one(5);
}

fn plus_one(x: i32) -> i32 {
    x + 1
}

メモリの開放について

  • 従来
    • ガベージコレクター(GC)を備えた言語では、GCは追跡し、使用されなくなったメモリをクリーンアップするため、考える必要はない
    • GCがなければ、メモリが使用されなくなったときを識別し、コードを呼び出して明示的に行う必要がある
      • 歴史的に難しいプログラミング問題
      • 忘れてしまうとメモリを無駄にする
      • 早すぎると、変数が無効になる
      • 1つの割り当てと1つの空きをペアにする必要がある
  • Rust
    • メモリを所有する変数がスコープ外になると、メモリは自動的に返される
{
    let s = String::from("hello"); // s is valid from this point forward
    println!("{}", s);
}                              // this scope is now over, and s is no longer valid

Appendix

変数と定数の違い

  • 定数
    • mutを定数とともに使用することは許可されてない
    • 定数はデフォルトでは不変であるだけでなく、常に不変
    • letの代わりにconstキーワードを使用して定数を宣言
    • 値の型に注釈を付ける必要がある
    • 定数の命名規則は、大文字 + アンダースコアで構成
const MAX_POINTS: u32 = 100_000;
fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
    println!("The value of MAX_POINTS is: {}", MAX_POINTS);
}

次回、所有権を
レクチャーできればと!

Made with Slides.com