-
Notifications
You must be signed in to change notification settings - Fork 20
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
Adding the contains method for the iterator trait #408
Comments
I think this would be a nice simplification to have. The itertools version uses Ideally we would fix (could you add |
|
We discussed this in the libs-api meeting. We're happy to have this as unstable for now, though the team was split over the usefulness of this compared to just directing users to use We did discuss the specific signature and think this signature would work better in practice since it allows for things like comparing fn contains<Q: ?Sized>(&mut self, item: &Q) -> bool
where
Self: Sized
Self::Item: PartialEq<Q>, |
Probably not a good idea but since closures and function items don't implement PartialEq we theoretically could add a then |
Function pointers do. Besides, your struct X;
impl PartialEq<X> for fn(&X) -> bool {
fn eq(&self, _: &X) -> bool {
false
}
}
fn check_fn_mut<I>(_: impl FnMut(&I) -> bool) {}
fn check_partial_eq<I>(_: &impl PartialEq<I>) {}
fn main() {
let g: fn(&X) -> bool = |_| true;
check_fn_mut::<X>(&g);
check_partial_eq::<X>(&g);
} |
I have a working implementation that passes all the test cases I wrote. /// Checks if the Iterator contains the value.
/// 'contains' is short-circuiting; in other words, it will stop processing
/// as soon as the closure returns `true`.
///
/// Performance:
/// This method checks the whole iterator, which takes O(n) time.
/// If the iterator is sorted, or a hash map please use the appropriate method.
///
/// Example:
/// ```
/// #![feature(contains)]
/// assert!(![1i32, 2i32, 3i32].iter().contain(&4i32));
/// assert!([Some(2i32), Option::<i32>::None].iter().contain(&None));
/// assert!([Some(2i32), Option::<i32>::None].iter().contain(&Some(2i32)));
/// assert!(!Vec::<i32>::new().iter().contain(&1i32));
/// assert!([1i32, 2i32, 2i32, 3i32].iter().contain(&2i32));
/// #[derive(PartialEq)]
/// struct Item {
/// value: i32,
/// }
/// assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().contain(&Item { value: 2i32 }));
/// assert!(["a", "b", "c"].iter().contain(&"b".to_owned()));
/// assert!(!["a", "b", "c"].iter().contain(&"d".to_owned()));
/// assert!(["a", "b", "c"].iter().contain(&"b"));
/// assert!(!["a", "b", "c"].iter().contain(&"d"));
/// assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"b"));
/// assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"d"));
/// assert!((1..1000).contain(500i32));
/// ```
///
#[unstable(feature = "contains", reason = "new API", issue = "127494")]
fn contain<Q: ?Sized>(&mut self, item: Q) -> bool
where
Q: PartialEq<Self::Item>,
Self: Sized,
{
for element in self {
if item == element {
return true;
}
}
return false;
}
} Should I submit a pull request now? |
Yes, but please rename the feature Also all your tests don't need to be the doctest - keep that simple, everything else can go in |
And don't forget to create a tracking issue for the |
(rust-lang/rust#127494 exists but the gate name and API need to be updated) |
@tgross35 I have renamed the function to has_item to avoid breaking code that uses the itertools contains function. |
@yonikremer you shouldn't need to care about itertool's naming given rust-lang/rfcs#3624 will likely be adapted. Just pick the most natural name. |
Proposal
Problem statement
Currently, checking if an iterator contains a specific element requires the use of any method, which involves more verbose and less intuitive code. Additionally, while the itertools crate provides a contains method, it is inefficient to rely on an external crate for such a fundamental and simple operation. This makes common tasks like searching for an element in an iterator more cumbersome than necessary, reducing code readability and developer efficiency.
Motivating examples or use cases
Example 1: Simplifying Search Logic
Current Approach:
Proposed Approach:
Example 2: Checking for Characters in Strings
Current Approach:
Proposed Approach:
Example 3: Consistency Across Collections
Current Approach:
Proposed Approach:
Solution sketch
The contains method will be added to the Iterator trait. This method will take an item and return true if any item in the iterator matches the given item, and false otherwise.
Example Implementation:
Alternatives
Alternative 1: Continue Using any
The primary alternative is to continue using any method. However, this approach is less readable and more verbose:
let contains_three = numbers.iter().any(|&x| x == 3);
Alternative 2: Use the itertools Crate
Another alternative is to use the itertools crate, which already provides a contains method. However, requiring an external crate for such a simple and fundamental operation is inefficient and unnecessary. Relying on external crates for basic functionality can lead to increased dependencies, larger binaries, and potential compatibility issues.
The text was updated successfully, but these errors were encountered: