web-dev-qa-db-ja.com

RustにはF#typedefと同等の慣用句がありますか?

私は既存のコードをRust 1.6で書き直していますが、ソース言語でtypedefで型にラベルを付けると非常に便利であることがわかりました。たとえば、私のカードゲームではF#のランク値は次のように定義されます。

type Rank = uint8
14
Erik Uggeldahl

From The Rust Programming Language section title Creating Type Synonyms with Type Aliass

Rustは、type aliasを宣言して、既存の型に別の名前を付ける機能を提供します。このために、typeキーワードを使用します。たとえば、次のようにエイリアスKilometersからi32を作成できます。

type Kilometers = i32;

現在、エイリアスKilometersi32の同義語です。 [...]、Kilometersは別個の新しいタイプではありません。タイプKilometersの値は、タイプi32の値と同じように扱われます。

type Kilometers = i32;

let x: i32 = 5;
let y: Kilometers = 5;

println!("x + y = {}", x + y);

あなたが読むべきものはもっとありますが、これは質問に答えます。


ちょっとした社説として、私はタイプエイリアスが人々がそれらを使用する多くの場所にぴったりだとは思いません。あなたのRankタイプがトランプのデッキと関係があると仮定すると、 enum または newtype 。その理由は、タイプエイリアスを使用すると、次のようなことができるためです。

let rank: Rank = 100;

これは、典型的なカードのデッキには無意味です。列挙型は制限されたセットです。これは、無効なRankを作成できないことを意味します。

enum Rank {
    One, Two, Three, Four, Five,
    Six, Seven, Eight, Nine, Ten,
    Jack, Queen, King, Ace,
}

impl Rank {
    fn from_value(v: u8) -> Result<Rank, ()> {
        use Rank::*;

        let r = match v {
            1 => One,
            2 => Two,
            // ...
            _ => return Err(()),
        };
        Ok(r)
    }

    fn value(&self) -> u8 {
        use Rank::*;

        match *self {
            One => 1,
            Two => 2,
            // ...
        }
    }
}

newtypeは単なるラッパータイプです。ラップされたタイプと比較して余分なスペースを消費せず、有効な値に制限できるメソッドを実装できる実際の新しいタイプを提供するだけです。無効な値を作成することは可能ですが、すべてのクライアントコードではなく、独自のコード内でのみ作成できます。

struct Rank(u8);

impl Rank {
    fn from_value(v: u8) -> Result<Rank, ()> {
        if v >= 1 && v <= 14 {
            Ok(Rank(v))
        } else {
            Err(())
        }
    }

    fn value(&self) -> u8 {
        self.0
    }
}

私は型のクイックプレースホルダーとして型エイリアスを使用する傾向があります。上記の例を書いている間、私は実際に次のように書いています。

type Error = ();

そしてResult<Rank, Error>を返しましたが、それは混乱を招くと思いました。 :-)

私がそれらを使用する他のケースは、私が隠したくない大きなタイプを短くすることです。これは、イテレータやResultsなどのタイプで発生します。これは 標準ライブラリを参照 です。何かのようなもの:

type CardResult<T> = Result<T, Error>;

fn foo() -> CardResult<String> {
    // ..
}
24
Shepmaster