Rustのloopのbreakで値を返す

ループ処理の中で成功した値だけを取り出したい。whileでは返せないし、std::iter::findではいけるだろうが、Futureを処理する必要がある場合は活用できない(findで処理させる場合中でawaitを使えない。処理する場合はStreamにしてFutureをすべて解決にしてから回すことになるから)の時に困るわけですが、loopbreak fooとして値を返せるようだ。

let mut i = 0;

assert_eq!(
    loop {
        i += 1;
        if i == 10 {
            break i;
        }
    },
    10
);

コーヒーを直火で再加熱できるシングルチタンマグが気に入っている

最近このシングルチタンマグにハマっています。普通にコップを電子レンジで加熱すればいいとは思うんですけど、それだとこたつから出なければいけない。

このコップならカセットコンロとかで加熱できるので、こたつから出ることなく再加熱とかできるのが便利。災害時にも飲み物を温めたりが容易にできます。

最近はスープもこれで作って飲んでます。一人分のスープを作るのに巨大な鍋だと難しいんですが、このコップでそれができるようになりましたよ。

IH対応の加熱できるコップとかもありそうですね。

Rustでタプル構造体でnewtypeデザインパターンを利用する

Rustの構造体ではタプル構造体というのを作ることができる

struct Example(String, String);

let example = Example("a".into(), "b".into());

assert_eq!(example.0, "a".to_string());
assert_eq!(example.1, "b".to_string());

これはnewtypeパターンというデザインパターンで利用されるらしい。より具体的な解説はRustで強めに型をつけるPart 1: New Type Patternが参考になった。

ざっくり解釈した感じだとこんなコードが

struct User {
    id: u32,
}

struct UserHasItem {
    user_id: u32,
    item_id: u32,
}

struct Item {
    id: u32,
}

let user = User { id: 1 };
let user_has_item = UserHasItem {
    user_id: 1,
    item_id: 1,
};
let item = Item { id: 1 };

こんな風に強めに型を付けてかけるらしい。

struct UserId(u32);
struct ItemId(u32);

struct User {
    id: UserId,
}

struct UserHasItem {
    user_id: UserId,
    item_id: ItemId,
}

struct Item {
    id: ItemId,
}

let user = User { id: UserId(1) };
let user_has_item = UserHasItem {
    user_id: UserId(1),
    item_id: ItemId(1),
};
let item = Item { id: ItemId(1) };

参考ページでは幽霊型という方法で同じような記述を何度もしなくても済む方法があったが、よっぽどのことがない限りは幽霊型のテクニックを使わなくても良さそうかなと思った。

RustでStructに対してデフォルト値を導入する

Example::new()としてデフォルト値を導入したいだけであれば、Defaultトレイトを利用するのが良い。Driveアトリビュートで設定する場合はその型のデフォルト値が自動で設定され、自分でデフォルト値を定めたい場合はDefaultトレイトを自分でインプリメントすることで実現できる。

#[derive(Default, Debug, PartialEq)]
struct Example {
    a: String,
    b: String,
}

let example: Example = Default::default();

assert_eq!(
    example,
    Example {
        a: "".into(),
        b: "".into()
    }
);

#[derive(PartialEq, Debug)]
struct Example2 {
    a: String,
    b: String,
}

impl Default for Example2 {
    fn default() -> Self {
        Self {
            a: "foo".into(),
            b: "bar".into(),
        }
    }
}

let example2: Example2 = Default::default();

assert_eq!(
    example2,
    Example2 {
        a: "foo".into(),
        b: "bar".into()
    }
);

https://www.utam0k.jp/blog/2018/05/28/rust_std_default/

Rustで既存のStructの値を一部変更した新しいStructを生成する

一部の値だけを変更した新しい構造体を..variableと書いて作ることができる。

#[derive(PartialEq, Debug)]
struct Example {
    a: String,
    b: String,
}

let example = Example {
    a: "foo".into(),
    b: "bar".into(),
};

let example2 = Example {
    b: "baz".into(),
    ..example
};

assert_eq!(
    example2,
    Example {
        a: "foo".into(),
        b: "baz".into(),
    }
)

参考

https://internals.rust-lang.org/t/proto-rfc-expanded-functional-record-update/3077

RustでStructからパターンマッチで値を取り出す

名前付き構造体から下記のようにしてパターンマッチで値を取り出すことができる。

#[derive(Clone)]
struct Example {
    a: String,
    b: String,
}

let example = Example {
    a: "foo".into(),
    b: "bar".into(),
};

let Example { a: c, b: d } = example.clone();

assert_eq!(c, example.a);
assert_eq!(d, example.b);