Skip to content

Tracking issue for Vec::extract_if and LinkedList::extract_if #43244

Closed

Description

@Gankra

Feature gate: #![feature(extract_if)] (previously drain_filter)

This is a tracking issue for Vec::extract_if and LinkedList::extract_if, which can be used for random deletes using iterators.

Public API

pub mod alloc {
    pub mod vec {
        impl<T, A> Vec<T, A>
        where
            A: Allocator,
        {
            pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A>
            where
                F: FnMut(&mut T) -> bool;
        }

        pub struct ExtractIf<'a, T, F, #[unstable(feature = "allocator_api", issue = "32838")] A = Global>
        where
            F: FnMut(&mut T) -> bool,
            A: Allocator;

        impl<T, F, A> Iterator for ExtractIf<'_, T, F, A>
        where
            F: FnMut(&mut T) -> bool,
            A: Allocator;

        impl<T, F, A> Drop for ExtractIf<'_, T, F, A>
        where
            A: Allocator;

        impl<T, F, A> Debug for ExtractIf<'_, T, F, A>
        where
            T: Debug,
            F: Debug,
            A: Debug + Allocator;
    }

    pub mod collections {
        pub mod linked_list {
            impl<T, A> LinkedList<T, A>
            where
                A: Allocator,
            {
                pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A>
                where
                    F: FnMut(&mut T) -> bool;
            }

            pub struct ExtractIf<'a, T, F, #[unstable(feature = "allocator_api", issue = "32838")] A = Global>
            where
                T: 'a,
                F: 'a + FnMut(&mut T) -> bool,
                A: Allocator;

            impl<T, F, A> Iterator for ExtractIf<'_, T, F, A>
            where
                F: FnMut(&mut T) -> bool,
                A: Allocator;

            impl<T, F> Debug for ExtractIf<'_, T, F, Global>
            where
                T: Debug;
        }
    }
}

Steps / History

Unresolved Questions

  • What should the method be named?
  • Should extract_if accept a Range argument?
  • Missing Send+Sync impls on linked list's ExtractIf, see comment

See #43244 (comment) for a more detailed summary of open issues.

Activity

  1. added
    B-unstableBlocker: Implemented in the nightly compiler and unstable.
    T-libs-api[DEPRECATED; DO NOT USE]
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Jul 19, 2017
  2. RalfJung commented on Jul 31, 2017

    @RalfJung
    Member

    Related issues:
    #25477
    #34265

  3. added a commit that references this issue on Aug 15, 2017
  4. bluss commented on Sep 4, 2017

    @bluss
    Contributor

    Maybe this doesn't need to include the kitchen sink, but it could have a range parameter, so that it's like a superset of drain. Any drawbacks to that? I guess adding bounds checking for the range is a drawback, it's another thing that can panic. But drain_filter(.., f) can not.

  5. rustonaut commented on Sep 11, 2017

    @rustonaut

    Is there any chance this will stabilize in some form in the not to far future?

  6. rustonaut commented on Sep 11, 2017

    @rustonaut

    If the compiler is clever enough to eliminate the bounds checks
    in the drain_filter(.., f) case I would opt for doing this.

    ( And I'm pretty sure you can implement it in a way
    which makes the compiler clever eneugh, in the worst
    case you could have a "in function specialization",
    basically something like if Type::of::<R>() == Type::of::<RangeFull>() { dont;do;type;checks; return } )

  7. jonhoo commented on Sep 22, 2017

    @jonhoo
    Contributor

    I know this is bikeshedding to some extent, but what was the reasoning behind naming this drain_filter rather than drain_where? To me, the former implies that the whole Vec will be drained, but that we also run a filter over the results (when I first saw it, I thought: "how is this not just .drain(..).filter()?"). The former on the other hand indicates that we only drain elements where some condition holds.

  8. rustonaut commented on Sep 23, 2017

    @rustonaut

    No idea, but drain_where sounds much better and is much more intuitive.
    Is there still a chance to change it?

  9. bluss commented on Sep 23, 2017

    @bluss
    Contributor

    .remove_if has been a prior suggestion too

  10. rustonaut commented on Sep 23, 2017

    @rustonaut

    I think drain_where does explains it the best. Like drain it returns values, but it does not drain/remove all values but just such where a given condition is true.

    remove_if sounds a lot like a conditional version of remove which just removes a single item by index if a condition is true e.g. letters.remove_if(3, |n| n < 10); removes the letter at index 3 if it's < 10.

    drain_filter on the other hand is slightly ambiguous, does it drain then filter in a more optimized way (like filter_map) or does if drain so that a iterator is returned comparble to the iterator filter would return,
    and if so shouldn't it be called filtered_drain as the filter get logically used before...

  11. Gankra commented on Sep 25, 2017

    @Gankra
    ContributorAuthor

    There is no precedent for using _where or _if anywhere in the standard library.

  12. jonhoo commented on Sep 25, 2017

    @jonhoo
    Contributor

    @gankro is there a precedent for using _filter anywhere? I also don't know that that is that a reason for not using the less ambiguous terminology? Other places in the standard library already use a variety of suffixes such as _until and _while.

  13. crlf0710 commented on Oct 23, 2017

    @crlf0710
    Member

    The "said equivalent" code in the comment is not correct... you have to minus one from i at the "your code here" site, or bad things happens.

  14. 253 remaining items

  15. added a commit that references this issue on Dec 17, 2024
  16. added a commit that references this issue on Feb 24, 2025
  17. added a commit that references this issue on Feb 25, 2025
  18. added 3 commits that reference this issue on Mar 11, 2025
  19. added this to the 1.87.0 milestone on Mar 21, 2025
  20. added a commit that references this issue on May 5, 2025
  21. added a commit that references this issue on May 5, 2025
  22. added a commit that references this issue on May 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-collectionsArea: `std::collections`B-unstableBlocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.T-libs-api[DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions