-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Change collect behaviour for maps #17111
Conversation
Collecting to a map is now a grouping operation, so the value type will need to implement `Extendable`. `from_iter` and `extend` were lossy before this change, which can be unexpected behaviour. The user should have to make a decision about how to handle adding values when there is already a value for a given key. To fix code broken by this, use a fold or a for loop. e.g. let map = iter.map(|x| (x, x.y)).collect::<HashMap<T, U>>(); Can become: let map = iter.fold(HashMap::new(), |mut map, x| { // You may want to use find_mut to update existing values. // This will overwrite an old value for a key with a new one. map.insert(x, x.y); map }); [breaking-change]
I think the current design is sensible, and it's consistent with other languages (C++, D, Python, [...]). The standard iterator methods only exist to provide sugar for common cases and being explicit about every algorithm choice is counter to that goal. The |
I wonder if we could have this via BTW, we don't necessarily want to be using Also, btw, rewriting the cc @aturon |
I agree with thestinger here, the current behaviour matches my intuition that extend is just sugar for pushing each of the elements individually (with room for optimization). For Sets and Maps, that means dropping duplicates. If you want to keep duplicates, you should be using a MultiMap (which we don't provide, but it isn't too hard to write one). |
I agree that the current semantics of @gankro to be clear, the use case here is more general than for multimaps, because the idea is that the value type has a way to "merge in" additional values. I could imagine adding this functionality as a separate constructor for maps -- something like But in general, we're trying to pare down |
If current behavior is desired/expected, then I agree with @aturon that this could live in an external crate. Closing. |
… r=Veykril fix: don't remove parentheses for calls of function-like pointers that are members of a struct or union Fixes rust-lang#17111
Current
collect
behavior for the Map types is lossy, where additional values per key are thrown away and only the last value is kept. I think the user should make an explicit decision regarding this behavior.Perhaps this warrants a different trait, or another static method to initialize maps from an iterator of pairs (with the lossy behaviour), i.e.
Hashmap::from_iter_lossy(..)
?I think it's worth looking closely at the changes in the 2nd commit as some of them may benefit from assertions that duplicates don't exist.
Also from an implementation standpoint, I'm sure I'm overlooking a better way to get an iterator from a single value, rather than
Some(v).move_iter()
.