Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Option::retain #70

Closed
kellerkindt opened this issue Jul 16, 2022 · 2 comments
Closed

Add Option::retain #70

kellerkindt opened this issue Jul 16, 2022 · 2 comments
Labels
ACP-accepted API Change Proposal is accepted (seconded with no objections) api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api

Comments

@kellerkindt
Copy link

Tracking issue rust-lang/rust#98934
PR for impl rust-lang/rust#98935

Proposal

Add new Option::retain<F>(&mut self, predicate: F) or similar to in-place replace self with None if it was Some(x) before and the predicate evaluated to false on the value x.

Problem statement

Writing if-let statements in-between value assignments can be hideous and disturb the reading flow when updating a bunch of values in (nested) structs.

fn some_fn(values: &mut MyBigFlagStruct) {
    values.x -= 7;
    values.y += 42;

    if let Some(z) = &value.z {
        if *z < values.x * values.y {
            values.z = None;
        }
    }

    values.some_counter += 1;

    if let Some(magic) = &values.magic {
        if *magic != 42 {
           values.magic = None;
        }
    }
}

Motivation, use-cases

This feature reduces the noise in the example from above:

fn some_fn(values: &mut MyBigFlagStruct) {
    values.x -= 7;
    values.y += 42;
    values.z.retain(|z| *z >= values.x * values.y);
    values.some_counter += 1;
    values.magic.retain(|magic| *magic == 42);
}

Solution sketches

Alternative name

Maybe retain_if?

values.magic.retain_if(|magic| *magic == 42);

Links and related work

What happens now?

This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.

@kellerkindt kellerkindt added api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api labels Jul 16, 2022
@the8472
Copy link
Member

the8472 commented Jul 25, 2022

Writing if-let statements in-between value assignments can be hideous

You could do this instead

values.z = values.z.take().filter(|z| *z >= values.x * values.y);

retain is shorter yet, but the statement about if-let is perhaps not the best motivation.

@m-ou-se
Copy link
Member

m-ou-se commented May 17, 2023

We discussed this in the libs meetup, and we think it'd be better to instead have Option::take_if that takes a predicate and returns the value if the predicate returned true (leaving None in the original option):

impl<T> Option<T> {
    pub fn take_if<F: FnOnce(&mut T) -> bool>(&mut self, predicate: F) -> Option<T>;
}

Feel free to open a tracking issue for take_if and send a PR to add it as an unstable feature.

@m-ou-se m-ou-se closed this as completed May 17, 2023
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 7, 2023
…imulacrum

Implement `Option::take_if`

Tracking issue: rust-lang#98934
ACP: rust-lang/libs-team#70 [accepted]
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Aug 8, 2023
Implement `Option::take_if`

Tracking issue: #98934
ACP: rust-lang/libs-team#70 [accepted]
thomcc pushed a commit to tcdi/postgrestd that referenced this issue Oct 17, 2023
Implement `Option::take_if`

Tracking issue: #98934
ACP: rust-lang/libs-team#70 [accepted]
@dtolnay dtolnay added the ACP-accepted API Change Proposal is accepted (seconded with no objections) label Nov 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ACP-accepted API Change Proposal is accepted (seconded with no objections) api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api
Projects
None yet
Development

No branches or pull requests

4 participants