Rust 1.6'daki mevcut kodlarımı yeniden yazıyorum ve bir yazım tipini typedef ile etiketlemek için kaynak dilde çok uygun buldum.Rust, F # typedefs ile idiomatik bir eşdeğer var mı?
type Rank = uint8
Rust 1.6'daki mevcut kodlarımı yeniden yazıyorum ve bir yazım tipini typedef ile etiketlemek için kaynak dilde çok uygun buldum.Rust, F # typedefs ile idiomatik bir eşdeğer var mı?
type Rank = uint8
itibaren The Rust Programming Language bölüm `type` Aliases başlıklı: Örneğin, kartım oyunda ben F # bir sıra değeri tanımladıktan
type
anahtar kelime başka türde bir takma ad bildirmek sağlar:gerçek bir tip sanki daha sonra bu türünü kullanabilirsiniztype Name = String;
:
type Name = String; let x: Name = "Hello".to_string();
Okuması gereken daha çok şey var ama bu soruya cevap veriyor. başyazısında biraz itibariyle
Rank
türünüzün bir kart destesiyle ilgili bir şey olduğunu varsayarsak,
enum
veya
newtype'u öneririm. Kartların tipik güverte saçmadır
let rank: Rank = 100;
: nedeni bir tür takma adı ile böyle bir şey yapabiliyor olmasıdır. Bir enum sınırlı bir kümedir. Bu geçersiz bir Rank
oluşturmak asla şu anlama gelir:
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,
// ...
}
}
}
A newtype sadece sarıcı türüdür. Sarılmış tiple karşılaştırıldığında fazladan alan tüketmez, yalnızca geçerli değerleri kısıtlayabilen yöntemleri uygulamanızı sağlayan gerçek bir yeni tür sağlar. Bu geçersiz değerler oluşturmak mümkündür, ancak sadece kendi kodu içinde, tüm istemci kodu:
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
}
}
Ben türlerinin hızlı tutucu olarak tip takma adları kullanma eğilimindedir. Yukarıdaki örnekler yazarken, aslında yazdı:
type Error =();
Ve Result<Rank, Error>
döndü ama sonra o kafa karıştırıcı olacağını düşündük. :-)
Onları kullandığım diğer durum, saklamak istemediğim daha büyük bir tür kısaltmaktır. Bu, see in the standard library olan yineleyiciler veya Result
s türleriyle olur. Şunlar gibi:
type CardResult<T> = Result<T, Error>;
fn foo() -> CardResult<String> {
// ..
}
Hızlı ve ayrıntılı yanıt için teşekkürler! Normalde değerlerimi standart güverte değerleriyle sınırlamak için enums kullanarak sizinle aynı fikirdeyim. Ancak, benim durumumda, "kart" terimini jenerik olarak kullanıyorum ve oyun kartını kullanmam, bu yüzden belirtilmemiş bir değer sıralamasına ihtiyacım var. Basit bir ikame ve eğer ek kısıtlamalar/mantık dayatmak istersem yeni bir tip kullanmak istiyorsam, bir tür takma ad kullanmam gerektiğini doğru mu anlıyorum? –
@ErikUggeldahl evet, kulağa doğru geliyor. Yeni bir tür ek kısıtlamalara veya mantığa izin verirken, takma ad sadece aynı şey için başka bir addır. – Shepmaster
@ErikUggeldahl sadece değerleri kısıtlamak değil. Bir takma ad, herhangi bir ek tip güvenlik sağlamaz çünkü ...yeni tip, ama aynı tür için başka bir isim. "Rank/5" 'i hesaplayabilmeniz ya da 'Rank' 'u8' alan bir işleve geçebilmeniz sizin için anlamlı mıdır? Bir tür takma ad bunu yapmanıza izin verdiğinden ('Rank' * * a' u8' olduğundan). Normalde, çok uzun ve karmaşık bir türdeyken ve daha kısa bir ifadeyle başvurmak istediğinizde, Rust'taki yazı tipi takma adlarını kullanmanız kolaylık sağlamak içindir (ancak diğer ad *, * türü ve bunun yerine her yerde kullanılmalıdır) –