Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I return None from a function that borrows from it's argument, or avoid needing to?

Tags:

rust

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?

like image 595
Iskar Jarak Avatar asked Sep 13 '25 10:09

Iskar Jarak


1 Answers

There are a few approaches you could take:

  1. Add another layer of Optionness, returning a Option<&Option<Foo>>. I’m guessing you don’t want to do this.

  2. 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,
        }
    }
    
  3. 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)
    }
    
like image 126
Chris Morgan Avatar answered Sep 15 '25 01:09

Chris Morgan