Rust dojo第17回を開催した

第17回です。

前回はこちら。

kdnakt.hatenablog.com

 

 

[第17回の様子]

2021/11/11に第17回を開催した。

諸事情により今週は木曜開催。文化の日が休みだったので間が空いてしまった...。

 

内容としてはRust By Example 日本語版の「5.4. エイリアス」、「6. 型変換」、「6.1. FromおよびInto」に取り組んだ。

 

曜日がいつもと変わったせいか、参加者はちょっと減って、全部で5人。

 

[学んだこと]

// `NanoSecond` を `u64`の別名として使用する。
type NanoSecond = u64;
type Inch = u64;

fn main() {
    // `NanoSecond` = `Inch` = `u64_t` = `u64`.
    let nanoseconds: NanoSecond = 5 as u64_t;
    let inches: Inch = 2 as u64_t;
}
  • UpperCamelケースを使わない場合は警告がでる
type u64_t = u64;

warning: type `u64_t` should have an upper camel case name
 --> src/main.rs:9:6
  |
9 | type u64_t = u64;
  |      ^^^^^ help: convert the identifier to upper camel case: `U64T`
  |
  = note: `#[warn(non_camel_case_types)]` on by default
  • #[allow(non_camel_case_types)]アトリビュートを使うと警告を非表示にできる
  • 注意すべき点として、エイリアスは新たな型を作っているわけではない:元の型のまま
type NanoSecond = u64;
type Inch = u64;

fn main() {
    let nanoseconds: NanoSecond = 5 as u64_t;
    let inches: Inch = 2 as u64_t;

    // 異なるエイリアスどうしでも演算できてしまう
    println!("{} nanoseconds + {} inches = {} unit?",
             nanoseconds,
             inches,
             nanoseconds + inches);
    // 5 nanoseconds + 2 inches = 7 unit?
}
type IoResult<T> = Result<T, IoError>;
  • 6. 型変換
  • Rustはトレイトを用いて型変換を行う:FromIntoなど
  • 6.1. FromおよびInto
  • Fromトレイトはある型を別の型から作る方法を定義するもの
  • strからStringへの型変換は以下のように行う
let my_str = "hello";
let my_string = String::from(my_str);
  • 自作の型(以下のNumber)への型変換は以下のように定義する
use std::convert::From;

#[derive(Debug)]
struct Number {
    value: i32,
}

impl From<i32> for Number {
    fn from(item: i32) -> Self {
        Number { value: item }
    }
}

fn main() {
    let num = Number::from(30);
    println!("My number is {:?}", num);
    // My number is Number { value: 30 }
}
  • IntoはFromの逆で、fromを呼び出す形になる
use std::convert::From;

#[derive(Debug)]
struct Number {
    value: i32,
}

impl From<i32> for Number {
    fn from(item: i32) -> Self {
        println!("From called");
        Number { value: item }
    }
}

fn main() {
    let int = 5;
    let num: Number = int.into();
    // from()が呼ばれ、From calledが出力される
    println!("My number is {:?}", num);
}
  • into()を呼び出す場合は、左辺に型定義が必須となる
let int = 5;
let num = int.into();

// 以下のコンパイルエラー
error[E0282]: type annotations needed
  --> src/main.rs:17:9
   |
17 |     let num = int.into();
   |         ^^^ consider giving `num` a type
  • Number型をi32に変換するためのIntoを実装すると次のようになる
use std::convert::From;
use std::convert::Into;

#[derive(Debug)]
struct Number {
    value: i32,
}

impl From<i32> for Number {
    fn from(item: i32) -> Self {
        println!("From called.");
        Number { value: item }
    }
}

impl Into<i32> for Number {
    fn into(self) -> i32 {
        println!("Into called");
        self.value
    }
}

fn main() {
    let int = 5;
    let num: Number = int.into();
    // From called.
    println!("My number is {:?}", num);
    // My number is Number { value: 5 }
    let int2: i32 = num.into();
    // Into called
    println!("int2: {}", int2);
    // int2: 5
}

 

[まとめ]

モブプログラミングスタイルでRust dojoを開催した。

久しぶりにドライバをやって緊張した。

 

今週のプルリクエストはこちら。

github.com