I have a slice of Option, and given a value, if that value is a valid index in the slice I want to use the value at that index, otherwise use None
.
Now, values need to be able to be reused, so I think I want to borrow from my slice, not move... Note that Foo
does not implement the Copy
trait and I'd prefer to keep it that way.
I need to do this often, so a function returning &Option<Foo>
seemed appropriate, with the addition of a lifetime specifier since obviously the return value shouldn't outlive the slice it is borrowed from. That leads me to:
fn get_or_none<'a>(data: &'a [Option<Foo>], bar: u8) -> &'a Option<Foo> {
match bar as usize {
idx if idx < data.len() => &data[idx],
_ => &None // obviously can't work
}
}
This is clearly wrong. I can cheat, for now, because I know for this particular application the first value in the slice will always be None (it's a property of my data, so to speak), but that's just avoiding the problem.
What should I do instead?
There are a few approaches you could take:
Add another layer of Option
ness, returning a Option<&Option<Foo>>
. I’m guessing you don’t want to do this.
Return an Option<&Foo>
instead of &Option<Foo>
:
fn get_or_none(data: &[Option<Foo>], bar: u8) -> Option<&Foo> {
match data.get(bar as usize) {
Some(&Some(ref foo)) => Some(foo),
_ => None,
}
}
Store a suitable None
as a static and return a reference to it. Its lifetime is 'static
(so long as Foo
is 'static
), so a reference to it can be shortened to 'a
with no problems.
static NO_FOO: Option<Foo> = None;
fn get_or_none(data: &[Option<Foo>], bar: u8) -> &Option<Foo> {
data.get(bar as usize).unwrap_or(&NO_FOO)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With