In Rust, Option
is defined as:
pub enum Option<T> {
None,
Some(T),
}
Used like so:
fn may_return_none() -> Option<i32> {
if is_full_moon {
None
} else {
Some(1)
}
}
fn main() {
let optional = may_return_none();
match optional {
None => println!("None"),
Some(v) => println!("Some"),
}
}
I'm not familiar with Rust internals, but initially I assumed it might work similar to Nullable
in .NET, so the compiled logic of my above Rust code would be like so:
// occupies `sizeof(T) + 1` memory space, possibly more depending on `Bool`'s alignment, so `Nullable<Int32>` consumes 5 bytes.
struct Nullable<T> {
Bool hasValue;
T value;
}
Nullable<Int32> MayReturnNone() {
if( isFullMoon )
// as a `struct`, the Nullable<Int32> instance is returned via the stack
return Nullable<Int32>() { HasValue = false }
else
return Nullable<Int32>() { HasValue = true, Value = 1 }
}
void Test() {
Nullable<Int32> optional = may_return_none();
if( !optional.HasValue ) println("None");
else println("Some");
}
However this isn't a zero-cost abstraction because of the space required for the Bool hasValue
flag - and Rust makes a point of providing zero-cost abstractions.
I realise that Option
could be implemented via a direct return-jump by the compiler, though it would need the exact jump-to values to be provided as arguments on the stack - as though you can push multiple return addresses:
(Psuedocode)
mayReturnNone(returnToIfNone, returnToIfHasValue) {
if( isFullMoon ) {
cleanup-current-stackframe
jump-to returnToIfNone
else {
cleanup-current-stackframe
push-stack 1
jump-to returnToIfHasValue
}
test() {
mayReturnNone( instructionAddressOf( ifHasValue ), instructionAddressOf( ifNoValue ) )
ifHasValue:
println("Some")
ifNoValue:
println("None")
}
Is this how it's implemented? This approach also works for other enum
types in Rust - but this specific application I've demonstrated is very brittle and breaks if you want to execute code in-between the call to mayReturnNone
and the match
statement, for example (as mayReturnNone
will jump directly to the match
, skipping intermediate instructions).