LoginSignup
1
1

The Rust Programming Languageを読み進める(3章)

Posted at

はじめに

The Rust Programming Languageを頭から読み進めてみる。読みながら要点をまとめていった記事です。

3章:一般的なプログラミングの概念

3.1章:変数と可変性

fn main() {    
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);

    const MAX_POINTS: u32 = 100_000;
    println!("The value of MAX_POINTS is: {}", MAX_POINTS);
}
The value of x is: 5
The value of x is: 6
The value of MAX_POINTS is: 100000
  • mutを外すとコンパイルエラーが発生
  • mutを外す=値が不変であることをコンパイラが担保
  • constは3桁毎に区切り、定義されたスコープ内でずっと有効
    • 型は常に注釈が必要
  • constletでの宣言は異なる
    • constは、コンパイル時定数と書き換え不可
    • letは、内部可変性があり変更可能なパターンあり
fn main() {
    let x = 5;
    let x = x + 1;
    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {}", x);
    }
    println!("The value of x is: {}", x);
}
The value of x in the inner scope is: 12
The value of x is: 6
  • シャドーイングを繰り返しているコード
  • シャドーイングによる和算が終われば、変数は不変に戻る
fn main() {
    let s = "test test";
    println!("s is: {}", s);

    let s = s.len();
    println!("s is: {}", s);
}
s is: test test
s is: 9
  • 文字型から数字型にシャドーイングしている例
  • 1回目にlet mut sで宣言し、let s = s.len();またはs = s.len();と定義すると、警告やエラーが発生

3.2章:データ型

数値・文字列

fn main() {
    let sum = 5 + 10;
    println!("sum is {}", sum);

    let difference = 95.5 - 4.3;
    println!("difference is {}", difference);

    let product = 4 * 30;
    println!("product is {}", product);

    let quotient = 56.7 / 32.2;
    println!("quotient is {}", quotient);

    let floored = 2 / 3;
    println!("floored is {}", floored);

    let remainder = 43 % 5;
    println!("remainder is {}", remainder);
    
    let boolean = false;
    println!("boolean is {}", boolean);
    
    let heart_eyed_cat = '😻';
    println!("heart_eyed_cat is {}", heart_eyed_cat);
}
sum is 15
difference is 91.2
product is 120
quotient is 1.7608695652173911
floored is 0
remainder is 3
boolean is false
heart_eyed_cat is 😻
  • 整数型の基準はi32、浮動小数型の基準はf64
  • 文字char型はユニコードで管理

配列・タプル

fn main() {
    let tup1 = (500, 6.4, "apple");
    let (x, y, z) = tup1;

    println!("The values of tup1: {}, {}, {}", x, y, z);
    
    let tup2: (i32, f64, &str) = (500, 6.4, "apple");
    let five_hundred = tup2.0;
    let six_point_four = tup2.1;
    let apple = tup2.2;
    
    println!("The values of tup2: {}, {}, {}", five_hundred, six_point_four, apple);
}
The values of tup1: 500, 6.4, apple
The values of tup2: 500, 6.4, apple
  • タプル型は、複数の型の要素を持てる複合型
  • 変数名.0のように、ピリオドで直接アクセス可能
  • let (x, y, z) = tup;の書き方は、1タプルを3つの変数に分配
fn main() {
    let a = [1, 2, 3, 4, 5];
    let b: [i32; 5] = [1, 2, 3, 4, 5];
    let c = [3; 5];
    
    println!("The values of a: {:?}", a);
    println!("The values of b: {:?}", b);
    println!("The values of c: {:?}", c);
    
    println!("The first value of a: {}", a[0]);
}
The values of a: [1, 2, 3, 4, 5]
The values of b: [1, 2, 3, 4, 5]
The values of c: [3, 3, 3, 3, 3]
The first value of a: 1
  • 配列もタプルと同様に複合型であるが、全要素が同じ型である必要あり
  • Rustの配列は固定長なので、変更は不可
    • 変更が予想される場合はベクタ型を使用

3.3章:関数

基本的な使い方

fn main() {
    func_a(5, 'h');
}

fn func_a(value: i32, unit_label: char) {
    println!("Output: {}{}", value, unit_label);
}
Output: 5h
  • 関数名はスネークケースで定義
  • 関数の仮引数の型は、宣言が必要

戻り値・式と文

fn main() {
    let x = func_b(5);
    println!("The value of x is: {}", x);
    
    let y = {
        let x = 3;
        x + 1 // ";"を付けるとエラー
    };
    println!("The value of y is: {}", y);
}

fn func_b(x: i32) -> i32 {
    x + 1 // ";"を付けるとエラー
}
The value of x is 6
The value of y is: 4
  • Rustは式ベースの言語で、セミコロンが無いとになり値を返す
  • 一方でセミコロンが付くとになり、処理を実行するが値は返さない
  • Cで使えるx = y = 6のような書き方は許さないため、let x = (let y = 6);はエラーが発生

3.4章:コメント

3.5章:制御フロー

if-else文

fn main() {
    let number = 6;

    if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else if number % 2 == 0 {
        println!("number is divisible by 2");
    } else {
        println!("number is not divisible by 4, 3, or 2");
    }
}
number is divisible by 3
  • Rustのif文は括弧が不要
  • いずれの分岐先でも戻り値の型は同一である必要あり

let文内でのif式

fn main() {
    let condition = true;
    let number = if condition { 5 } else { 6 };

    println!("The value of number is: {}", number);
}
The value of number is: 5
  • 別変数での評価結果に基づいて、変数に代入が可能

loop

fn main() {
    let mut count = 0;
    'counting_up: loop {
        println!("count = {}", count);
        let mut remaining = 10;

        loop {
            println!("remaining = {}", remaining);
            if remaining == 9 {
                break;
            }
            if count == 2 {
                break 'counting_up;
            }
            remaining -= 1;
        }

        count += 1;
    }
    println!("End count = {}", count);
}
count = 0
remaining = 10
remaining = 9
count = 1
remaining = 10
remaining = 9
count = 2
remaining = 10
End count = 2
  • loopはシングルクオテーションでラベルを付与可能
  • 内部の'counting_upに到達したら、外側のloopから脱出している
    • 見慣れないが、ただのラベルと思えば良い

while

fn main() {
    let mut number = 3;
    
    while number != 0 {
        println!("{}!", number);
        number -= 1;
    }
    
    println!("LIFTOFF!!!");
}
3!
2!
1!
LIFTOFF!!!

for

fn main() {
    let a = [10, 20, 30];
    let mut index = 0;

    // whileでイテレーション
    while index < 3 {
        println!("the value is: {}", a[index]);
        index += 1;
    }
    
    // forループでイテレーション
    for element in a {
        println!("the value is: {}", element);
    }
}
the value is: 10
the value is: 20
the value is: 30
the value is: 10
the value is: 20
the value is: 30

特記事項なし

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1