-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Rename Iterator::fold_first to reduce and stabilize it #79805
Conversation
@rfcbot merge |
Team member @m-ou-se has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
I'm somewhat skeptical of the name In the summary put together by @jagill, they said this:
And I think that's exactly where I fell. When I saw the name The name Overall, I'd say my opinion here is pretty weak and this is probably a minor quibble. But it would be good to hear if anyone else shares this concern. |
Kotlin docs are here, and at least the implementation on the The scala docs are here and seem to accept supertypes as well:
As it's no OOP language, Rust doesn't really have supertype vs subtype relationships for all types. The closest it has are traits. But you can't have trait type params in Rust so there would be no way to encode this constraint. Maybe having an Into bound would bring us closer to Kotlin and Scala: fn reduce<V>(f: impl Fn(V, Self::Item) -> V) -> Option<V> where Self::Item: Into<V>, { /*...*/ } |
I'm hoping this is the right place to comment. I'm not sure if this was already raised. Coming from JavaScript my bias and preference is for With Rust seemingly already having |
I strongly favored Apparently Offtopic: another curious discovery, somehow I thought that |
I think I echo @BurntSushi's sentiment a bit in not really favoring |
See #68125 (comment) for my reasoning for the name |
@rfcbot concern naming The more I think about this personally, the more I think |
@KodrAus @BurntSushi Would either/both of you be in favor of stabilizing the feature under the name I would personally really like this feature stabilized. It's in most major languages, and the comments in the tracking issue suggest that many people (myself included) find it very useful. If the other team members would accept fold_first, I'd move we try to stabilize it under that name. |
I would be okay with |
I still think While reading code, While writing code, I don't see any problem with someone looking for the |
I definitely agree with that. My problem is that I perceive I'm not a huge fan of |
I think this is not much of a problem in the docs, since the signatures are visible, there are examples, there's an explanation, and both functions link to eachother in their documentation.
I think this is a much bigger problem. A good name can make all the difference while reading new code. Picking a name that would cause people to have to look things up when there is an alternative that wouldn't, just seems bad. |
I think I might be convinced by that. I'll noodle on it. @KodrAus You also expressed skepticism at the name. What do you think? |
I'm glad we're moving away from the map/filter/fold are the classic iterator combinator examples, but fold is I think rather famously more difficult for users new to the API to understand. Having more variations on the concept I worry will make things more obscure for users trying to get an intuitive understanding of the API surface. I think reduce would be especially bad for this: its common knowledge that reduce and fold are two names for the same concept; I wouldn't envy users new to these API patterns trying to understand why we have both, how they are different, and which to use for which use cases. On the other hand, for users who already understand the API this replaces a two-liner: a call to next followed by a call to fold; I don't think it really carries its weight. |
FP patterns make it into mainstream with force, so nowadays I would expect all competent developers to have conceptual understanding of "fold" and friends. In fact, the opposite is true: developers would expect "fold with init value" and "fold, starting with 1st element" to exist in any competent language/standard library. Lack of either of these would be a) time wasted in searching for it b) mild disappointment due to rust stdlib falling behind even Java in ergonomics ;)
Well, it is two-liner now. Here is the difference:
|
I almost never use folds in Rust code, and instead prefer for loops because I think folds are more difficult to read. So I don't really feel like this addition is that great. But, I also don't feel strongly against it either, because folds are occasionally nice and I recognize that reasonable people can disagree. And in particular, I think it's bad to start making decisions on some notion of what a "competent" developer knows or doesn't know. I would rather not try to litigate the usefulness or clarity of folds in general here. That's just not going to move us forward. But rather, whether this specific API carries its own weight. |
Ah, I eventually approved the original PR after it was shown that we could replace a few ad-hoc helpers in the I think @withoutboats captured my skepticism very succinctly:
Most methods on |
@vchekan's code is a good example showing why we need this method - he has written the code that is both incorrect and inefficient: let v = vec![1,2,3];
// Will result in `7` because .iter() is called twice
let mut vi = v.iter();
v.iter().fold(vi.next().cloned(), |a, i| a.map(|a| a + i));
// Correct version
let mut vi = v.iter();
vi.next().cloned().map(|a| vi.fold(a, Add::add)); std method would guard against this problem :) About the naming: I'm personally still in favour of |
As an outsider, I'm not sure if I agree with the assertion of Coming from JavaScript I preferred From what I gather, this functionality is already considered niche, so I assume it won't be added, but |
I like the For me, the difference between Rust is in the minority of languages that does not have function overloading. So it is more useful in Rust to take advantage of more "fine-grained" naming conventions. Also, the difference between
|
Having worked in many languages, I consider either Fold and reduce are definitely synonyms. There's no question about that, as @BurntSushi has pointed out. But Scheme provided both Regarding whether the method pulls its weight, this is a case where it's more surprising to not have the method. Nearly every language that provides |
There is also precedent in |
a681d48
to
24e0940
Compare
Rebased to include a new usage of the feature in @bors r=KodrAus |
📌 Commit 24e0940 has been approved by |
Rename Iterator::fold_first to reduce and stabilize it This stabilizes `#![feature(iterator_fold_self)]`. The name for this function (originally `fold_first`) was still an open question, but the discussion on [the tracking issue](rust-lang#68125) seems to have converged to `reduce`.
Rename Iterator::fold_first to reduce and stabilize it This stabilizes `#![feature(iterator_fold_self)]`. The name for this function (originally `fold_first`) was still an open question, but the discussion on [the tracking issue](rust-lang#68125) seems to have converged to `reduce`.
Rollup of 9 pull requests Successful merges: - rust-lang#74304 (Stabilize the Wake trait) - rust-lang#79805 (Rename Iterator::fold_first to reduce and stabilize it) - rust-lang#81556 (introduce future-compatibility warning for forbidden lint groups) - rust-lang#81645 (Add lint for `panic!(123)` which is not accepted in Rust 2021.) - rust-lang#81710 (OsStr eq_ignore_ascii_case takes arg by value) - rust-lang#81711 (add #[inline] to all the public IpAddr functions) - rust-lang#81725 (Move test to be with the others) - rust-lang#81727 (Revert stabilizing integer::BITS.) - rust-lang#81745 (Stabilize poison API of Once, rename poisoned()) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
@m-ou-se I think By the way, happy chinese new year! |
If you search for reduce, it shows fold. And everybody is fine with it. Why should it not be vice versa? |
This stabilizes
#![feature(iterator_fold_self)]
.The name for this function (originally
fold_first
) was still an open question, but the discussion on the tracking issue seems to have converged toreduce
.