4 ms·
Rust doesn't have optionals built-in. The language has no special support for them (beyond the try operator); just like Java, Rust's optional type is provided b
by TazeTSchnitzel 4y ago
Rust doesn't have optionals built-in. The language has no special support for them (beyond the try operator); just like Java, Rust's optional type is provided by the standard library, but it could be trivially implemented yourself and your implementation would have the same behaviour and performance characteristics. It's literally just:
enum Option<T> {
Some(T),
None,
}
What makes Rust fast here is that it has value types and can optimise them.
- tialaramex 4y agoEven for the try operator (?) it is these days just an unstable Trait that you are welcome to implement for your own types. Once that's stabilized it's not any different from how types can implement PartialEq and get == and !=. The extra edge beyond not needing boxing is from niches, if T doesn't occupy all possible bit representations Rust will squeeze None into one of the unused bit values. Several standard library types have such niches, but today there is no stable way to make your own yet.
- masklinn 4y ago> Several standard library types have such niches, but today there is no stable way to make your own yet. However note that if a type has suitable niches enums will automatically take advantage of those. So that’s more of a concern with T than with a bespoke Option, that’ll work OOTB.
- tialaramex 4y agoYes, Rust's Guaranteed Niche Optimisation says if you make this: enum Foo<T> { Nasty, Nice(T), } ... and T has a niche, it is guaranteed that Foo<T> has the same size as T and Nasty just slots into the niche. In practice, other fancier things will get optimised, but Rust doesn't guarantee exactly what will or will not be handled, e.g. if the niche has room for four things, and I make an enum with four extra plain variants, the guarantee doesn't apply but probably that'll work.
- atq2119 4y ago> today there is no stable way to make your own [types with niches] yet. Not strictly speaking true since you can define enum types and those usually have niches?
- tialaramex 4y agoGood point
- winrid 4y agoYeah I was on my phone thinking, isn't Optional implemented as something else? and yeah it's an enum. oops :) Which in the Rust world probably just needs to be one byte, probably a bit in most cases, in a register for state. I don't think Java will be that optimized with value types. Even if the heap allocation is gone, there's still probably going to be a sizable object header?
- peterashford 4y agoNo. Value types do not have "sizeable object headers". They don't have object headers at all.
- deleted 4y ago[deleted]
- winrid 4y agoWhat about the fields in the type?
- kaba0 4y agoThe current proposal plans on not defining anything about where and how those things are gonna be stored, but the plan behind all that (and how plenty of classes of the JVM have been designed even in foresight) is that a value type can be flattened (and each value type field recursively so). But do note that it is only a possibility — the JVM might decide that flattening all that would have a negative impact due to increase in size and opt for storing object references. But the important part is losing identity - even if a field a few layers deep won’t be flattened, it doesn’t have to work the same way for the same data at every place - the JVM now is free to instead of copying the reference only, can choose to copy the value. This trivializes things like escape analysis as well (we can just stack allocate this value class, if it does turns out to escape, just copy to the heap).
- chrismorgan 4y ago> The language has no special support for them (beyond the try operator) In the interest of full and strict accuracy: see the enum’s full definition at https://github.com/rust-lang/rust/blob/d610b0c514b9ccb0dad5d0b77ce4c518f71b92c8/library/core/src/option.rs#L559-L572 https://github.com/rust-lang/rust/blob/d610b0c514b9ccb0dad5d.... There are a few points of specialness about Option that you can’t use elsewhere: • #[rustc_diagnostic_item = "Option"]: the compiler knows about Option for the purpose of improving its error messages. I’m not sure how this is used, and am not looking it up now. • #[lang = "None"] and #[lang = "Some"]: lang items allow the compiler to hook things up, like knowing the + operator maps to the core::ops::Add trait. https://github.com/search?q=repo%3Arust-lang%2Frust+%28option_none_variant+OR+option_some_variant%29&type=code https://github.com/search?q=repo%3Arust-lang%2Frust+%28optio... suggests that these lang items are only being used by Clippy, to provide better diagnostics. So if you use your own Option type, you won’t get Clippy lints related to Option. • I suppose there are also the #[stable] attributes, which can’t be used outside the standard library, and which cause visible changes in generated documentation. When talking about strict accuracy, I guess that counts! Anyway: for practical purposes this is just minor diagnostics and documentation stuff, not actual functionality, about which there is nothing special. Since you mentioned the try operator, might as well look at the trait implementations on Option too, https://doc.rust-lang.org/std/option/enum.Option.html#trait-implementations https://doc.rust-lang.org/std/option/enum.Option.html#trait-.... There are a few things marked “This is a nightly-only experimental API.”, which you can implement yourself if you’re willing to take that stability risk; they’re all linked to try_trait_v2, which is what backs the try operator, `?`. Once it, or its successor, is stabilised, we’ll effectively be back to there being absolutely nothing special about Option, as you’ll be able to implement those traits for your own Option type as well.