Something like replace_map() method on Option<>?

Hi there, I have a code snippet where I want to replace the value inside an Option<> by manipulating the existing value.

However, I was curious if there is some one-liner method on Option<> already present that is more idiomatic? Look at the commented out code for what I am trying to find.

struct Foo {
        val: Option<i32>
    }

    impl Foo {
        pub fn change_val(&mut self) {
            if let Some(v) = self.val.take() {
                self.val = Some(v * 2);
            }

             // Is there anything like this available?
            // self.val.replace_map(|v| v * 2);
        }
    }

There’s as_mut that allows one to get mutable reference to the value directly. Alternatively, one can write

lf let Some(val) = &mut self.val {
    *val = val * 2
}
1 Like

That is right; I am following this section from the book, where I need to change the value inside the Option (mutating is not an option).
…

pub fn request_review(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.request_review())
        }
    }

You can use Option::map but I don’t know if it’s better.

self.state = self.state.take().map(|s| s.request_review())
1 Like

Yes - this is more or less what I had in mind; silly, that I couldn’t think of it :slight_smile:

// A bit odd because it's not how one would
// expect map to be used
self.state.as_mut().map(|x| *x *= 2);

// Options are iterable
for x in &mut self.state {
    *x *= 2;
}

// One-liner
self.state.iter_mut().for_each(|x| *x *= 2);
1 Like

Aha! I hadn’t noticed this. But I think this pattern will not address the request_review example where the Option’s value needs to be replaced (and not just modified in place).

Right. For the request_review example, @leudz’s answer is highly idiomatic.

1 Like