[Idea] `Ref{,Mut}::<Option<T>>::transpose`

I found myself needing this function while working on my project:

impl Ref<Option<T>> {
    fn transpose(self) -> Option<Ref<T>> {
        if self.is_some() {
            Some(Ref::map(self, |inner| unsafe {
                inner.as_ref().unwrap_unchecked()
            }))
        } else {
            None
        }
    }
}

Is this is idiomatic way of doing this? Does it make sense to add a standard library function for this, or is this too niche?

1 Like

Here’s a maybe nicer implementation:

use std::cell::Ref;

fn transpose1<T>(this: Ref<Option<T>>) -> Option<Ref<T>> {
    Ref::filter_map(this, |opt| opt.as_ref()).ok()
}

use std::cell::RefMut;

fn transpose2<T>(this: RefMut<Option<T>>) -> Option<RefMut<T>> {
    RefMut::filter_map(this, |opt| opt.as_mut()).ok()
}

I don’t like the naming “transpose” too much, because it glosses over the (potentially significant) side-effect that this operation unlocks the RefCell in the None case, wheras AFAIR other “transpose” methods are usually side-effect-free conversions between essentially equivalent alternatives. (I have not searched for “all the ‘transpose’s” though, so feel free to point me to more wild existing examples.)

3 Likes

Thanks! This is much nicer and actually solved another problem I had.

because it glosses over the (potentially significant) side-effect

I see. Hmm, what's a better name? ok_or_unlock?