types rust type-alias

types - ¿Rust tiene un equivalente idiomático a F#typedefs?



type-alias (1)

Estoy reescribiendo mi código existente en Rust 1.6 y he encontrado que es muy conveniente en el idioma de origen etiquetar un tipo por tipodef. Por ejemplo, en mi juego de cartas tengo un valor de rango en F # definido como:

type Rank = uint8


Desde la sección de Rust Programming Language titulada `type` Alias :

La palabra clave type te permite declarar un alias de otro tipo:

type Name = String;

Luego puede usar este tipo como si fuera un tipo real:

type Name = String; let x: Name = "Hello".to_string();

Hay más que deberías leer, pero esto responde la pregunta.

Como un poco de editorial, no creo que un alias de tipo encaje bien en muchos lugares donde las personas los usan. Suponiendo que tu tipo de Rank represente algo relacionado con una baraja de cartas, te sugiero un enum o un newtype . La razón es que con un alias de tipo puede hacer algo como esto:

let rank: Rank = 100;

Lo cual no tiene sentido para una baraja de cartas típica. Una enumeración es un conjunto restringido. Esto significa que nunca puedes crear un Rank inválido:

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, ()> { let r = match v { 1 => One, 2 => Two, // ... _ => return Err(()), }; Ok(r) } fn value(&self) -> u8 { match *self { One => 1, Two => 2, // ... } } }

Un newtype es solo un tipo de envoltura. No consume espacio adicional en comparación con el tipo envuelto, simplemente proporciona un nuevo tipo real que le permite implementar métodos que pueden restringir a valores válidos. Es posible crear valores no válidos, pero solo dentro de su propio código, no todos los códigos de cliente:

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 } }

Tiendo a usar alias de tipo como marcadores de posición rápidos de tipos. Mientras escribía los ejemplos anteriores, de hecho escribí:

type Error = ();

Y devolvió un Result<Rank, Error> , pero luego pensó que sería confuso. :-)

El otro caso que los utilizo es acortar un tipo más grande que no quiero ocultar. Esto sucede con tipos como iteradores o Result s, que puede ver en la biblioteca estándar . Algo como:

type CardResult<T> = Result<T, Error>; fn foo() -> CardResult<String> { // .. }