-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
RFC: Boxes vs Containers - Naming schemes for element access #7887
Comments
I think it's silly to have redundant functions/methods doing It would be much simpler to just use the |
@thestinger: I agree in principle, but the problem here is that methods on |
I'm talking about everything returning an |
I've been mulling this over. My preference at this point is to do away with the "ref" and "consume" suffixes, and make "get" mean reference, and "unwrap" mean by value. So, today's option get becomes unwrap, unwrap stays the same, get_ref turns into get, map stays as map, map_consume turns into map_unwrap, and consume_iter turns into unwrap_iter. |
bblum, |
My thought about that was "unwrap means might fail", but "map means won't fail" with higher precedence. I dunno, maybe it is better to keep that as consume, but I'd like to see one or the other word go away. Would it be any better to replace all "unwrap" with "consume"? |
@bblum: I think we should prefer functions like .map() to consume self if On Tue, Jul 23, 2013 at 8:01 PM, Ben Blum [email protected] wrote:
|
@bblum: looking back at my patch, I also added .map_ref() in the case you didn't want to pay the cost to clone the container. Hows does that pattern sound? |
That (foo and foo_ref) was my original leaning, but then I thought about The other qualm I had with that idea is that ARC |
Keep unwrap for the case where you get "the whole content" out of a thing. I agree Kimundi, I don't really agree with any of your alternatives. Separate Option from the containers. Option is a building block for the latter. |
A note to |
Not for Option, since it's so central, it needs a lot of sugar |
The challenge which approach do we pick for the shortest name? I converted What if we made the container's
|
I don't think consuming is usually what you want for containers, and lots of them won't be able to do it. |
@thestinger: How so? I'm using the term consume in this case to mean transferring the ownership of the contained elements from one container to another. Any container that allows for removing of elements (e.g. not bloom filters) should be able to support this kind of operation. |
Consume would often be I'm not sure if you would be able to write consume for a container like a list (chunked or not), without unsafe code that's likely to break if drop flags are removed. |
@thestinger: By
It wouldn't be that hard to optimize away Regarding persistent containers, I totally agree, and it makes total sense for their Regarding writing consume for a mutable singly linked list, you would need an intermediate structure that stores the consumed items in reverse order. All you need to do then is unreverse them. It'd also be |
@erickt: I was thinking about the complexity of consuming and building up a new tree compared to just doing the operation in-place. Default methods like |
I added a consume iterator to treemap recently. |
(no unsafe, o(n), very tidy!) |
More to the point of the bug, I think i prefer no suffix means by-ref, we use the suffix _move rather than take, consume or unwrap, and partial functions are funneled into either conditions or options with an _opt suffix. |
@graydon: So Speaking towards the bug, do we need partial forms of functions like |
Isn't |
One observation: Persistent collections will not be able to support a "consume" operation. |
@nikomatsakis: Yeah, I figured you'd need a separate trait for each of these functions. |
According to #7887, we've decided to use the syntax of `fn map<U>(f: &fn(&T) -> U) -> U`, which passes a reference to the closure, and to `fn map_move<U>(f: &fn(T) -> U) -> U` which moves the value into the closure. This PR adds these `.map_move()` functions to `Option` and `Result`. In addition, it has these other minor features: * Replaces a couple uses of `option.get()`, `result.get()`, and `result.get_err()` with `option.unwrap()`, `result.unwrap()`, and `result.unwrap_err()`. (See #8268 and #8288 for a more thorough adaptation of this functionality. * Removes `option.take_map()` and `option.take_map_default()`. These two functions can be easily written as `.take().map_move(...)`. * Adds a better error message to `result.unwrap()` and `result.unwrap_err()`.
This PR does a bunch of cleaning up of various APIs. The major one is that it merges `Iterator` and `IteratorUtil`, and renames functions like `transform` into `map`. I also merged `DoubleEndedIterator` and `DoubleEndedIteratorUtil`, as well as I renamed various .consume* functions to .move_iter(). This helps to implement part of #7887.
Does anybody have a succinct explanation of the current consensus on this subject for https://github.com/mozilla/rust/wiki/Doc-detailed-release-notes? |
If we do #9355 (which I'd be totally in favor for), it would pretty much reduce all discussion here to I'm kinda embarrassed that I never got the idea that you might not need three different versions of accessors for |
This is an alternative version to rust-lang#8268, where instead of transitioning to `get()` completely, I transitioned to `unwrap()` completely. My reasoning for also opening this PR is that having two different functions with identical behavior on a common datatype is bad for consistency and confusing for users, and should be solved as soon as possible. The fact that apparently half the code uses `get()`, and the other half `unwrap()` only makes it worse. If the final naming decision ends up different, there needs to be a big renaming anyway, but until then it should at least be consistent. --- - Made naming schemes consistent between Option, Result and Either - Lifted the quality of the either and result module to that of option - Changed Options Add implementation to work like the maybe Monad (return None if any of the inputs is None) See rust-lang#6002, especially my last comment. - Removed duplicate Option::get and renamed all related functions to use the term `unwrap` instead See also rust-lang#7887. Todo: Adding testcases for all function in the three modules. Even without the few functions I added, the coverage wasn't complete to begin with. But I'd rather do that as a follow up PR, I've touched to much code here already, need to go through them again later.
…ne, r=flip1995 Remove hidden code lines in Clippy's lint list This PR removes code lines from Clippy's lint list, which would also be hidden, when generating docs with rustdoc. "A picture is worth a thousand words"... and here are even two pictures: **Before:** ![image](https://user-images.githubusercontent.com/17087237/138952314-676dd9e7-ee80-459e-b521-bc42d8d03517.png) **After:** ![image](https://user-images.githubusercontent.com/17087237/138952684-4fef969d-6880-4434-a338-b1a5a45539f0.png) --- changelog: none r? `@camsteffen` (Since you implemented the code block filtering 🙃 )
Right now there is much confusion and inconsistency about the naming of functions that deal with elements in types that wrap one or more of them. We need to find a consistent way to deal with that.
First, some terminology:
Examples: Vector, Hash Map, Linked List.
Examples: Option, Cell, ~T, ARC.
I'm also defining a elementary set of operations you can perform on containers and boxes in regard to an arbitrary chosen element
E
(named in all-caps to differentiate from actual function names below):(&'a self) -> &'a E
(&'a mut self) -> &'a mut E
(&mut self) -> E
(self) -> E
In regard to naming schemes, I see a number of possibilities:
Unify boxes and containers
This would be the globally most consistent and reusable way, but also the most ugly one. We define a set of functions for working with an arbitrary 'next' element on an container. For example in stack-terminology:
fn top(&'a self) -> &'a E
- REF, fail if emptyfn peek(&'a self) -> Option<&'a E>
- REF or Nonefn top_mut(&'a mut self) -> &'a mut E
- REF_MUT, fail if emptyfn peek_mut(&'a mut self) -> Option<&'a mut E>
- REF_MUT or Nonefn pop(&mut self) -> E
- TAKE, fail if emptyfn pop_opt(&mut self) -> Option<E>
- TAKE or Nonefn pop_consume(self) -> E
- UNWRAP, fail if emptyfn pop_consume_opt(self) -> Option<E>
- UNWRAP or None.Separate boxes and containers, consistent box naming scheme
Containers and Boxes are separate concepts. Containers are build around a terminology and operations that make most sense to them. They probably wouldn't support UNWRAP and might not support the others either, depending on their specific semantics.
Boxes gain their own more concise and strictly consistent terminology, based around the box metaphor:
fn get(&'a self) -> &'a E
- REF, fail if emptyfn get_opt(&'a self) -> Option<&'a E>
- REF or Nonefn get_mut(&'a mut self) -> &'a mut E
- REF_MUT, fail if emptyfn get_mut_opt(&'a mut self) -> Option<&'a mut E>
- REF_MUT or Nonefn take(&mut self) -> E
- TAKE, fail if emptyfn take_opt(&mut self) -> Option<E>
- TAKE or Nonefn unwrap(self) -> E
- UNWRAP, fail if emptyfn unwrap_opt(self) -> Option<E>
- UNWRAP or None.Separate boxes and containers, convenient box naming scheme
This one is quite similar to the prior one, but shuffles names and definitions around to provide a nicer set of function names for the common operations:
fn get(&'a self) -> &'a E
- REF, fail if emptyfn get_opt(&'a self) -> Option<&'a E>
- REF or Nonefn get_mut(&'a mut self) -> &'a mut E
- REF_MUT, fail if emptyfn get_mut_opt(&'a mut self) -> Option<&'a mut E>
- REF_MUT or Nonefn take(&mut self) -> Option<E>
- TAKE or Nonefn unwrap(self) -> E
- UNWRAP, fail if emptyThe last one is probably the most convenient as it's optimized for common "I know it is not
None
"Option
usecases:opt.get()
- " Do something with the content of a Option, but keep it in place."opt.unwrap()
- "Move the content out of a Option, throw the Option away"opt.clone().unwrap()
oropt.get().clone()
- "Get a copy of the content"opt.take().unwrap()
- "Move the content out of a Option, replace the Option with None"Hm, this writeup is only half as comprehensive and cohesive as I wanted it to be, I hope it's still understandable.
The text was updated successfully, but these errors were encountered: