How to get the opposite behavior of '?' for Option?

For context, this is part of a very bare-bones GUI library. I would ideally want to be able to write something like this:

impl Widget for MyWidget {
    fn get_drop_target(&self, pos: Vec2D) -> Option<DropTarget> {
        self.get_drop_target_in_children(pos)?;
        Some(self.make_drop_target())
    }
}

The idea being that MyWidget is some kind of parent or layout that should check if its children have some kind of drop target available and return that if possible, otherwise return its own drop target. At the moment the behavior of ? makes it so that None is returned when encountered but if Some is encountered, execution continues. Is there an easy way to get the opposite of this behavior without using a whole if let statement? In this example it wouldn't be so bad but I have a couple widgets which have more custom behavior that requires calling methods on individual children, it would be really nice to be able to write something like:

impl Widget for Complicated {
    fn get_drop_target(&self) -> Option<DropTarget> {
        self.child1.get_drop_target()?;
        if condition {
            self.child2.get_drop_target()?;
        }
        self.child3.get_drop_target()?;
        None
    }
}

Well, if-let already is syntactic sugar for what it would otherwise be: a full-blown match expression with the None arm executing no code.

What you could do is write a macro that reduces the if-let further to a one-liner. That might help to preserve the overview.

1 Like

That sounds like a good option. I'll make something like the try! macro but since I'll never need to chain it it won't have the same problems with bulkiness. Code if someone wants to copy/paste:

/// "Return If Some", use it like the `try!` macro.
#[macro_export]
macro_rules! ris {
    ($value:expr) => {
        if let ::std::option::Option::Some(value) = $value {
            return Some(::std::convert::Into::into(value));
        }
    };
}
1 Like

I would actually probably use some of the combinator methods on Option

.or() or .unwrap_or() seem like what you want