-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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 or_default to Entry APIs #44344
Add or_default to Entry APIs #44344
Conversation
r? @BurntSushi (rust_highfive has picked a reviewer for you, use r? to override) |
|
||
The tracking issue for this feature is: [#44324] | ||
|
||
[#41020]: https://github.com/rust-lang/rust/issues/44324 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The link label is wrong.
src/liballoc/btree/map.rs
Outdated
/// # Examples | ||
/// | ||
/// ``` | ||
/// use std::collections::BTreeMap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to add #![feature(entry_or_default)]
to the doc test, otherwise it won't pass.
/// ```
/// #![feature(entry_or_default)]
/// # fn main() { // <-- note that the `fn main` is required
/// use std::collections::BTreeMap;
/// // etc.
/// assert_eq!(map["poneyland"], None);
/// # }
/// ```
src/liballoc/btree/map.rs
Outdated
/// use std::collections::BTreeMap; | ||
/// | ||
/// let mut map: BTreeMap<&str, String> = BTreeMap::new(); | ||
/// let s = "hoho".to_string(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the point of let s = "hoho".to_string()
?
src/libstd/collections/hash/map.rs
Outdated
/// use std::collections::HashMap; | ||
/// | ||
/// let mut map: HashMap<&str, Option<usize>> = HashMap::new(); | ||
/// let s = "hoho".to_string(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(ditto for everything)
a43d350
to
35c7943
Compare
@kennytm the |
@jonhoo |
I guess |
@jonhoo |
@arielb1 why |
'or_default' doesn't immediately convey that an insertion happens. In fact one can misconstrue this as returning a default value without inserting anything. Also, meta question - what's the bar for adding purely convenience APIs? I'd imagine it has to be fairly high to warrant putting oneself on the hook for documenting, testing, and otherwise maintaining these convenience methods. Users are also forced to see a larger API surface and the "important" bits may get buried amidst convenience functions. |
@vitalyd we could make it |
@jonhoo, I'm just sideline commenting :). However, if I did have a horse in the race, I think I'd want the insert part to be prominent in the name (especially since the other methods have that, so symmetry, if nothing else, is nice). I think the bigger question is the bar for convenience methods, as mentioned. My own $.02 is this doesn't meet that due to how trivial, albeit slightly more wordy, the existing usage is today. But I don't know what core libs team's threshold is for that. |
@kennytm, fair enough. The Vec::resize_all may allow further optimizations though based on that issue (didn't read beyond that so don't know if that's actually true or not). So something that's convenient but can also exploit internals to optimize better is almost definitely a win. Option/Result unwrap_or_default is probably more common than Entry usage, but I don't have stats to back that up. |
I guess this should be changed to |
@jonhoo In the same style, one could add |
@H2CO3: I really like that idea! Though isn't that what |
@jonhoo let option = Some("foo");
let len_or_zero = option.map(str::len).unwrap_or_default(); Using let option = Some("foo");
let len_or_zero = option.map_or_default(str::len); An implementation could be literally: impl<T> Option<T> {
…
pub fn map_or_default<F, U>(self, f: F) -> U
where F: FnOnce(T) -> U,
U: Default {
self.map(f).unwrap_or_default()
}
…
} |
@H2CO3 I suspect that |
@jonhoo I understand; but in my opinion the point is not that it's hard to implement. It's as simple to implement as
|
ping for review @BurntSushi ! |
My own personal opinion is that there is a cost to the number of methods we add to these APIs, but we've traditionally been pretty loose with adding convenience methods (like this one) as long as one can articulate a reasonable use case for them. I do think there is room for us to get more principled on this (for example, a tool that recognizes code that can be replaced with a hypothetical convenience method in the ecosystem could tell us how common something really is), but I don't think we need to litigate that on this PR. I also feel like the name @bors r+ |
📌 Commit 9389d26 has been approved by |
Add or_default to Entry APIs As argued for in #44324, this PR adds a new `or_default` method to the various `Entry` APIs (currently just for `BTreeMap` and `HashMap`) when `V: Default`. This method is effectively a shorthand for `or_insert_with(Default::default)`.
☀️ Test successful - status-appveyor, status-travis |
As argued for in #44324, this PR adds a new
or_default
method to the variousEntry
APIs (currently just forBTreeMap
andHashMap
) whenV: Default
. This method is effectively a shorthand foror_insert_with(Default::default)
.