'for' loops in Rust do the same: they create an iterator and then iterate over that.
You can write the exact same loop with `let mut iter = v.iter(); while Some(x) = iter.next()`.
'for' loops in Rust are purely syntax sugar, and I somewhat wish they didn't exist. They provide you two ways of doing the same thing, but one of them hides the details from you. Having 'for' as a keyword is nice for folks coming from other languages, but then it hides the possibility of other interesting usages, like cloning an iterator inside a loop.
Which is funny, because whenever I encounter a language for which `for` *doesn't* work this way it feels antiquated. I do however wish another keyword was used in many cases, becuase `for` in C and Go is so much different then `for` in Rust or Python. I think the higher-level case (Rust and Python) should really use a word like `foreach` or maybe something compeletely different like `itr`, although I get that they want to "look" more like C
Is "hiding" in the sense that you just need to have read the docs or know how the language works at a pretty basic level really a problem, or even a negative? I would certainly say that the readability and clarity on the form of loop being used is a bigger win, either way.
It's true that they're just sugar but Rust does explain how the for-in loop de-sugars and you've over-simplified considerably. Your syntax also doesn't quite work.
The value is in idiom, turning everything into loop expressions (The "while" keyword is also just sugar, Rust's only fundamental loop is named loop) makes it harder to discern what's actually going on.
If you want to clone the iterator in some cases rather than consuming it, that should look different so that reviewers will see what you're up to.
It should be `v.into_iter()`, and that distinction matters because of ownership / move semantics.
It just so happens that for most collections, `IntoIter` is also defined for references to them, which typically gives you the same behavior that `.iter()` would give.
In addition to the points that sibling comments have made about how you're not quite right with the exact semantics of for loops (which also take ownership via `into_iter` and therefore are a bit different from `while let`), it's worth pointing out that if you peek a bit further in to MIR, all loops in Rust just desugar into the `loop` keyword with manual breaking, including `while`. It's not really clear to me why for loops in particular bother you.
I don't really get the point of the article. Even if I knew little about python, would be it surpsing that a language with no real basic types is probably abstracting a lot?
Even a simple i=0, i=i+1 is "hiding" a lot in python then.
TL;DR: if you want a general looping construct that works no matter the container type, you need an iterator protocol that types can opt into. This is a standard technique adopted by most programming languages that are not explicitly low-level, and has existed for the past 60[1] years. The OP (re)discovered it and thought it was worth blogging about.
Well, it is kind of interesting to see how the very basic programming building block (iteration) gets generalized without incurring syntactic costs. Whether it's worth a place on the HN front page is debatable, though.
[1] Too lazy to track the actual first implementation, but I'd be astonished if the concept wasn't well-known by the 70's.
The best known programming language in the 1980s, BASIC, had a FOR that was limited to counting. A lot of people without formal CS education would think Python’s for can go over a finite set of things and live happily at that level of abstraction without ever needing to peek under the bonnet and learn how iterators work (in Python).
12 comments
[ 4.7 ms ] story [ 52.9 ms ] threadYou can write the exact same loop with `let mut iter = v.iter(); while Some(x) = iter.next()`.
'for' loops in Rust are purely syntax sugar, and I somewhat wish they didn't exist. They provide you two ways of doing the same thing, but one of them hides the details from you. Having 'for' as a keyword is nice for folks coming from other languages, but then it hides the possibility of other interesting usages, like cloning an iterator inside a loop.
The value is in idiom, turning everything into loop expressions (The "while" keyword is also just sugar, Rust's only fundamental loop is named loop) makes it harder to discern what's actually going on.
If you want to clone the iterator in some cases rather than consuming it, that should look different so that reviewers will see what you're up to.
It just so happens that for most collections, `IntoIter` is also defined for references to them, which typically gives you the same behavior that `.iter()` would give.
Even a simple i=0, i=i+1 is "hiding" a lot in python then.
Comparing to forEach in JS is incorrect because forEach is an method of Array.
You should compare it to `for...of` in JS. Both operate on iterators.
Article is missing an important distinction between iterators and other "array like" types (including strings):
Iterators don't have to stop, e.g., they can take from a generator that never ceases.
Both Python and JS are happy to loop forever if the iterator never stops.
Well, it is kind of interesting to see how the very basic programming building block (iteration) gets generalized without incurring syntactic costs. Whether it's worth a place on the HN front page is debatable, though.
[1] Too lazy to track the actual first implementation, but I'd be astonished if the concept wasn't well-known by the 70's.