-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 add foreach to iterators #582
Conversation
|
||
# Detailed design | ||
|
||
The design is simple, just syntacting suggar around a loop that consumes the iterator as seen in |
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.
I believe you mean "syntactic sugar" here.
i think |
I too prefer |
I think this would be really nice. 👍 to Side note: I had to do some clicking around to figure out what is being proposed here. Could you put the main idea in the RFC itself? |
+1 |
This is called |
However, since |
@SimonSapin: I had the same thought at first, but this comment on reddit convinced me that it can be quite nice to end a chain of iterator methods with an application of a closure instead of splitting it up into a separate iterator chain plus a for loop. But maybe it really just belongs in itertools, where it already is. |
While this is interesting, I think the way to go at this point is to demonstrate wide usage in a Cargo crate like itertools. The bar should be high to move thing into std. |
I don't think that would be the best metric for measuring desire in this feature. I personally think this would be very convenient, but not to the point where I would necessarily bring in a separate dependency just for that. I agree that the bar should be high, but this is a very simple addition, and one that is a core part of many other languages that have similar iteration/chaining/streams APIs (such as Scala, C#, Java 8, and Ruby to name a few). I think the RFC would benefit from including a code example motivating the addition of this method. While I think for loops are great, I do think it's nice to not have to break the chain of iteration methods just to force the side-effecting changes to go through. let mut somechain = xs.iter().take(5).filter(|x| x.is_thing()).map(|x| x + 1);
for thing in somechain {
// do side effecting operation
println!("{:?}", x);
} It would be nicer to be able to just do this for certain short cases: xs.iter()
.take(5)
.filter(|x| x.is_thing())
.map(|x| x + 1)
.each(|x| println!("{:?}", x)); I'm not adamant about including this, but it did always strike me as odd that this method was missing from iterators. |
I used to think that way. And then I learned to love Cargo. Publishing and using very small crates like |
That said some things still should go into std eventually. But in the mean time, real world usage experience can bring feedback of changes you might want to do before setting thing is backward-compatibility stone. |
@SimonSapin Oh that's not what I meant. I don't mind bringing in another dependency if the thing I want to use is necessary and useful. What I meant was that in my case, and I bet other people, if this method were available to me out of the box I would readily use it, but otherwise I don't care enough about it to warrant bringing in a dependency simply for it. Take your With that in mind, it's also why I wouldn't mind too much if this weren't accepted, but it does feel like it's conspicuously missing from the list of iterator methods to others who are familiar with similar iterator APIs. And I still agree with you that we should be careful/cautious about the things that are proposed to be added to the std; I wholeheartedly agree. I think it's a good idea to, like you say, first get feedback about such proposals, but I think that's already what this RFC is for; it's not really an earth-shattering proposal with deep and complex ramifications, AFAIK. We do have to draw the line somewhere. After all, if we accept this, then what's not to stop us from adding a bunch of other simple proposals until the std is undirect and bloated, right? Sure, but my argument is that this method is a very common component of similar APIs, I think of it as an iteration 'primitive' (such as @larroy: Please include a code example showing specifically how this may be useful. Feel free to use mine or a better one you could come up with. It's nice to have self-contained RFCs so people could easily get a full picture of what you intend, even if the use of your proposed method seems very obvious to you. |
This already existed (it was called Most Rust users considered |
@blaenk: Your code example is just deliberately making the |
@strcat: It's not some sleight of hand attempt to deceive anyone to show that the temporary is necessary; everyone knows the temporary isn't necessary. I realized I should have changed or clarified it for this very reason but I had to go AFK before I got a chance. The reason I separated it out in the example was because that's what I normally do when the chain gets very long, though in that example it's not particularly long. When the chain is very long I like to have each segment on its own line for readability, and as a result it makes the for loop look very weird, so I separate it out that way.
|
It looks perfectly fine without a temporary when following the "official" Rust coding style. |
@thestinger: when it fits in one line, it's ok: for x in xs.iter().take(5).filter(|x| x.is_thing()).map(|x| x + 1) {
// do side effecting operation
println!("{:?}", x);
} But if you want to break it up, line by line, it's getting pretty ugly IMHO and rightward: for x in xs.iter()
.take(5)
.filter(|x| x.is_thing())
.map(|x| x + 1) {
// do side effecting operation
println!("{:?}", x);
} From the visual point of view, and that's my subjective opinion, having an |
Does |
Even shorter is |
@Ericson2314 @P1start I mentioned on the discuss thread, that iterator.fold((), |_, x|{
// for_each body;
}) is equivalent to proposed function. It is also much clearer in intent compared to |
FWIW, there's also |
So, it seems like debate has mostly settled down at this point. (From what I can tell, we have two camps: One saying that a method like this is worthwhile since its name signals "my callback carries a side-effecting operation", and the other saying "you should just be writing this as a for-loop, not pure method composition." Well, I guess there's also a third camp, perhaps a subcamp of the second, that says "if you really want to do this without making a for-loop, you can use pre-existing methods for it"; but that is not really a counter-argument since the first camp sees intrinsic value in the name Regarding @SimonSapin 's point about Cargo: I believe the core team agrees with him, and wants to encourage things that can go into third party libraries to actually go up on Cargo, regardless of whether they are tiny/trivial things. (The main reason not to put this up on Cargo is if we wanted to encourage people to use it, but I suspect that in general we want to encourage people to use for-loops instead, all other things being equal.) The RFC seems to have been abandoned by its author, since they have not responded to requests from the community for the addition of a motivating example to the RFC itself. @larroy am I mistaken about this? |
Something similar has been added to itertools http://bluss.github.io/rust-itertools/doc/itertools/trait.Itertools.html |
Ah, great! and Here's the method itself: http://bluss.github.io/rust-itertools/doc/itertools/trait.Itertools.html#method.foreach @larroy you said "similar"; are the semantics of the above method different than what you proposed here, to your knowledge? In any case, I'm inclined at this point to close this ticket. |
Well, if there's no intention to put it in rust then we can close as it's already in itertools for those who care. |
As per the most recent discussion, I'm going to go ahead and close this RFC. |
No description provided.