let mut store = None;
let operand = match §ion[1] {
Symbol::Name(name) =>
reference_manager.get_reference(name.as_str())?.get_variable()?,
Symbol::Literal(literal) =>
{
store = Some(TypeFactory::get_default_instantiated_type_for_literal(literal, stack_sizes, program_manager)?);
store.as_ref().unwrap()
},
_ => return Err("Operator must be followed by a Literal or Name".to_string())
};
Here is my current code - one of the match arms retrieves a reference whereas the other creates a value. Is there a more idiomatic way to achieve this than using a mutable option? This could be correct but it feels incorrect from both my experience with other languages and the rust compiler claiming that store is never read.
It's hard to say since you haven't offered the code which one may compiler but you don't need mut here. Something like this should work:
let store;
let operand = match §ion[1] {
Symbol::Name(name) =>
reference_manager.get_reference(name.as_str())?.get_variable()?,
Symbol::Literal(literal) =>
{
store = TypeFactory::get_default_instantiated_type_for_literal(literal, stack_sizes, program_manager)?;
&store
},
_ => return Err("Operator must be followed by a Literal or Name".to_string())
};
Cow is your friend if you need to store either an owned value or a borrow (it’s quite useful even if you don’t need the actual "copy on write" part).
@khimru Thanks! Not sure why but I assumed that you had to make sure that a variable was guaranteed to be initialised. Makes sense that that's only true if you use it after.
That's natural assumption since in most languages where variables don't have lifetimes that's indeed the case.
In Rust, though, variables can be invalid (which is told in any tutorial usually with String moved out example) and that, naturally, means they can exist in “invalid” state. Making sure you can go from “invalid” state to “assigned” state was natural decision and made initialisation symmetrical to deinitialisation.