Skip to content
New issue

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

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

Already on GitHub? # to your account

Implement Extend trait #142

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,14 @@ impl<T> Slab<T> {
}
}

impl<T> Extend<T> for Slab<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for value in iter.into_iter() {
self.insert(value);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inserting values into a slab without saving the resulting indexes is usually not useful. Do you have a use-case for this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about that, I personally have a use case where the resulting indices aren't used, but it might be good to not use the trait at all and just have a function that returns Vec<usize> or an iterator like that instead?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like this might work:

pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) -> Vec<usize> {
    iter.into_iter().map(|x| self.insert(x)).collect()
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think I prefer the original version. A Vec<usize> will often not be the form that the user wants the indexes in.

I think it's okay to just say that users who want the indexes can iterate it themselves.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about -> impl Iterator<Item=usize>?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could make sense, but it would be a larger change. I don't think we can do it without a custom iterator.

Not having a return value allows us to follow the existing trait.


impl<T> ops::Index<usize> for Slab<T> {
type Output = T;

Expand Down
8 changes: 8 additions & 0 deletions tests/slab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ fn insert_with_vacant_entry() {
assert_eq!(123, slab[key]);
}

#[test]
fn extend() {
let mut slab = Slab::with_capacity(5);
slab.extend(1..9);
assert_eq!(slab[5], 6);
assert_eq!(slab.len(), 8);
}

#[test]
fn get_vacant_entry_without_using() {
let mut slab = Slab::<usize>::with_capacity(1);
Expand Down