Ergonomic Option handling inside Ref::map

Viewed 114

I have a function that tries to return a Ref out of a Refcell. The reference is behind an Option, and I'd like to be able to return the reference or an error if the Option is None.

Currently, I am checking beforehand if there it is none and returning an error if it is. Afterwards, I am calling unwrap() on the Option inside Ref::map in order to return the object.

Is there a more ergonomic way to do this? This seems very annoying to do (multiple borrows(), etc.) Option has a method ok_or that turns it into a Result type. Is there a way to use that here?

Here is a Rust playground to reproduce the minimal example:

    pub fn get_thing_convenience(&self) -> Result<Ref<f32>, Box<dyn Error>> {
        if self.thing.borrow().is_none() {
            return Err(Box::new(MyError("blah".into())))
        }
        let thing = Ref::map(self.thing.borrow(), |t| t.unwrap());

        Ok(thing)
    }
1 Answers

There used to be a filter_map method, but it was removed because the functionality can (usually?) be implemented safely with a performance cost, and it wasn't clear whether filter_map was the best way to go (it would special-case Option, complicates things with the recent changes/debate over Try, and it might just make more sense for there to be a way to transform Ref<Option<T>> into Option<Ref<T>>). However, in the meantime, there is a crate ref_filter_map that does exactly this and is "believed to be safe".

You could use it like this:

use ref_filter_map::ref_filter_map;

pub fn get_thing_convenience(&self) -> Result<Ref<f32>, Box<dyn Error>> {
    ref_filter_map(self.thing.borrow(), |t| t)
        .ok_or_else(|| Box::new(MyError("blah".into())))
}

However, you may want to consider simply doing it the slow way if you are worried about unsafety.

Related