4 ms·
In Rust, you'd define an `enum` of two types. enum Either { Type1(T1), Type2(T2), } let's say you get a value of type Either then you
by iopq 10y ago
In Rust, you'd define an `enum` of two types.
enum Either {
Type1(T1),
Type2(T2),
}
let's say you get a value of type Either
then you can match on them:
match value {
Type1(v) => func(v),
Type2(v) => func2(v),
}
- flukus 10y agoDoes that let you work with the default type? What I was doing in c#: function(T1 thing) { //do normal T1 stuff here var foo = arg as T2; if (foo != null) foo.T2Stuff(); //more normal T1 stuff } If I'm understanding your example I would have to wrap all the T1 stuff in a match.
- mathw 10y agoYes, you do. There is no idea of a 'default' type here, because each variant of the enum is treated exactly the same. Your C# example assumes an inheritance relationship between T1 and T2 (i.e. T2 inherits from T1, so you can pass it to something expecting a T1 reference). Rust doesn't have type inheritance, so the only way you can define relationships between types is to have something external tell you how to package them together, which is what the enum would do here. So it's not a parent-child relationship between the types, it's a new thing which says "here is a thing which can be a T1 or a T2 but not both at once". Not having OO does require you to think somewhat differently about how to build your data structures in Rust. I've found my intuition from Haskell is a stronger guide when working with Rust, but since Rust's type system is much more like that in an ML-family language this makes quite a bit of sense! Sadly this does increase the learning curve for more mainstream languages. (Rust does have trait inheritance, but all that says is that to implement trait T2 you have to also implement trait T1, and thus anything working with a T2 can assume that thing is also a T1).
- flukus 10y agoThanks. The above example was actually using two entirely different interfaces. It seems like rust is quite similar to the OO subset I prefer to use. In this particular case it would have been a better match because traits can implement methods. Rust is on my "to learn" list over the holidays.
- iopq 10y agoYes, you'd have to wrap it in a match. But maybe you don't have to. If T1 is the normal case, then there's a type in Rust called Result that handles this kind of pattern. fn potentially_failing(thing: Result<Type1, Type2>) { thing.map(|foo| success_case(foo)); } this will only execute in the success case and ignore the error case map_err does the same, but only touching the error case
- flukus 10y agoThanks, that's pretty cool.