Rust是否具有与F#typedef相同的惯用语?

Eri*_*ahl 12 types rust type-alias

我在Rust 1.6中重写了我的现有代码,我发现在源语言中通过typedef标记类型非常方便.例如,在我的纸牌游戏中,我将F#中的等级值定义为:

type Rank = uint8
Run Code Online (Sandbox Code Playgroud)

She*_*ter 22

来自Rust Programming Language部分标题为使用类型别名创建类型同义词:

Rust提供了声明类型别名的功能,以便为现有类型提供另一个名称.为此,我们使用type关键字.例如,我们可以创建别名Kilometersi32,像这样:

type Kilometers = i32;
Run Code Online (Sandbox Code Playgroud)

现在,别名Kilometers是同义词i32; [...],Kilometers不是一个单独的新类型.具有该类型的值Kilometers将被视为与类型的值相同i32:

type Kilometers = i32;

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

println!("x + y = {}", x + y);
Run Code Online (Sandbox Code Playgroud)

还有更多你应该阅读,但这回答了这个问题.


作为一个社论,我不认为类型别名非常适合人们使用它们的很多地方.假设你的Rank类型代表的东西做的一副扑克牌,我建议任何一个enumNEWTYPE.原因是使用类型别名可以执行以下操作:

let rank: Rank = 100;
Run Code Online (Sandbox Code Playgroud)

对于典型的牌组而言,这是荒谬的.枚举是限制集.这意味着您永远不能创建无效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,
            // ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一个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
    }
}
Run Code Online (Sandbox Code Playgroud)

我倾向于使用类型别名作为类型的快速占位符.在编写上面的例子时,我实际上写道:

type Error = ();
Run Code Online (Sandbox Code Playgroud)

并返回了一个Result<Rank, Error>,但后来认为这会令人困惑.:-)

我使用它们的另一种情况是缩短我不想隐藏的更大类型.这种情况发生在迭代器或Results 等类型中,您可以在标准库中看到它们.就像是:

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

fn foo() -> CardResult<String> {
    // ..
}
Run Code Online (Sandbox Code Playgroud)

  • @ErikUggeldahl它不仅限制了价值.别名不提供额外的类型安全性,因为它不是...新类型,而是同一类型的另一个名称.能够计算"Rank/5"或将"Rank"传递给带有"u8"的函数是否有意义?因为类型别名允许你这样做(因为`Rank`*是*a`u8`).你通常在Rust中使用类型别名是为了方便你有一个非常长而复杂的类型,并希望更简洁地引用它(但别名*是*类型,应该在任何地方代替它使用) (2认同)