3 ms·
One can look at Option<T> as an interface/base class that can be satisfied by a T or by (). Indeed, in Java-style languages, one occasionally sees implementatio
by dbaupp 9y ago
One can look at Option<T> as an interface/base class that can be satisfied by a T or by (). Indeed, in Java-style languages, one occasionally sees implementations that have an Option abstract base class, with two subclasses, Some and None. Both enums and subclassing are forms of polymorphism, the main conceptual difference is the polymorphism being closed or open (respectively). The fact that Rust adds extra layers of types/syntax on top of the raw polymorphism is syntactic sugar, just a disguise.
One could actually even express the Option concept as a trait, with manual downcasts:
trait OptionLike {
type Contained;
fn is_some(self) -> bool;
fn as_some(self) -> Some<Self::Contained>;
}
struct Some<T> { value: T }
impl<T> OptionLike for Some<T> { ... }
struct None<T> { _phantom: ...<T> }
impl<T> OptionLike for None<T> { ... }
Under this scheme, Option<T> is expressed as a trait object like Box<OptionLike<Contained=T>>, and the whole thing looks a lot more like the OOP/subclassing approach.
In any case, the fact that unwrap is clearly documented to fail on the None case is orthogonal: it's an invariant about the (sub)types of it's arguments that isn't expressed in the signature.