3 ms·
From the link: > A for expression extracts values from an iterator, looping until the iterator is empty. They look like this: for i in 1..10 { printl
by steveklabnik 2y ago
From the link:
> A for expression extracts values from an iterator, looping until the iterator is empty.
They look like this:
for i in 1..10 {
println!("{i}");
}
And they're totally fine to use in Rust, I agree that the article is not exactly accurate here.
EDIT: Okay you edited your comment to say this doesn't count. Sure. This is what the author of the post was talking about, though.
- John23832 2y agoI guess the statement >>That's not really the case. For loops are certainly less common compared to C, but they are completely fine to use. Forcing every loop into an iterator-chain style can quickly become an unreadable mess. Implies a C-style for loop, some sort of counting accumulator, and an update expression. That doesn't exist in rust. That's all I was saying. I know who you are, so I know I'm preaching to the preacher.
- steveklabnik 2y agoGotcha. I don't think it implies a C-style for loop, guess we just read things differently :)
- bee_rider 2y agoThe author of the post says: > For loops are not idiomatic in Rust - writing Fortran-ey code instead of iterators will lead to pain and slower loops. Spending time reading the examples in the iterator docs and the community solutions in the exercisms will help a lot. I think they are talking about C style for loops or Fortran style do loops, they explicitly contrast against iterators. Edit: Although, I wonder, what does an iterator like you’ve shown compile down to? I’d imagine Rust is smart/modern enough and that iterator is common enough that the assembly emitted looks a lot like a c for loop. Or better.
- steveklabnik 2y agoI understood them to be saying that they would prefer (0..10).iter().for_each(|x| println!("{x}")) over the thing that I wrote. Many folks do not think of Rust's for loops as using iterators under the hood, and so will often talk about them as though they don't use iterators, even though they technically do.
- miguelraz 2y agoAuthor here, long time no see Steve! When I wrote this, my main takeaways were numerical computations with arrays, which don't tend to use for loops in Rust, and which require grokking iterators for maximum performance and rayon-parallelism boons. To a Julia audience, seeing this style of iterator chaining is quite a new flavor to think about composing computation, so I wanted it was with that audience in mind that I wrote this.
- steveklabnik 2y agoHey hey! Yeah I think that makes sense! I don't do that kind of work and so it's more usual in the kinds of code I write.
- dist1ll 2y agoIIRC for loops compile down to a while loop with the same body, that drives the given iterator with .next(), until it returns None. Since the .next() implementation of std::ops::Range is essentially an i++, you'll quickly arrive at a similar representation as classic C for-loop.
- tialaramex 2y agoRust only "really" has one loop, the one named loop. Loop is an infinite loop that you can break out of (using the break keyword of course). All the other syntax, including both "for" and "while" loops and the related but technically different "while let" loop, while useful to humans to communicate intent, aren't semantically different - and so they're transformed early in compilation, they are just "syntax sugar" and are de-sugared into rather elaborate loops with their exit condition now a loop break condition etc. But yes, as in C++ and similar languages, the iterators generate the same machine code as you'd have gotten for writing the C-style for loop from the 1970s, it's just that in Rust you literally can't write that loop.
- bee_rider 2y agoNow I’ve become confused as to what it means for a language to have a thing. Hypothetically if you do for i in 1..10 { println!("{i}"); } (From earlier) the compiler should have enough information to fully unroll the loop if it feels like it. So it is a different syntax from the programmer’s point of view. Maybe it goes through some “this is a loop” stage inside the compiler. But then hypothetically the assembly output could… end up not even having a loop at all (fully unrolled, no jump back, haha).
- steveklabnik 2y agoWhat your parent is saying is that the compiler treats that loop as { let result = match IntoIterator::into_iter(1..10) { mut iter => loop { let next; match iter.next() { Some(val) => next = val, None => break, }; let i = next; let () = { println!("{i}"); }; }, }; result } (95% sure I got that correct) And so in some sense, "loop" is more primitive than "for". > But then hypothetically the assembly output could… end up not even having a loop at all Absolutely, with any of these loops, the compiler may not emit a loop in assembly. And in this case, that seems to be true: https://godbolt.org/z/7Gq69Gvre https://godbolt.org/z/7Gq69Gvre
- kstrauser 2y agoThat's nearly identical to Python's approach, too. It doesn't have C-style loops, just ones that consumer iterators. for i in range(10): print(i) consumes 1 value at a time from the `range(10)` generator. `for` has no special knowledge of numbers or ranges or any of that.