Remix.run Logo
WhyNotHugo 4 hours ago

'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.

bigfishrunning 4 hours ago | parent | next [-]

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

adrian_b 2 hours ago | parent | next [-]

Iterators and the loops of the form "forall X in A do ..." have been invented simultaneously with the appearance of the first version of the language C (i.e. around 1974), in the languages Alphard and CLU.

From Alphard and CLU, loops of this form have passed into one of the versions of the language Algol 68 (1977), and from there into the UNIX Bourne shell (1979), which inherited a few Algol 68 syntax features (because its author had worked at writing Algol 68 compilers).

Iterators and "forall" loops have begun to spread into mainstream programming languages, e.g. into C++, only a couple of decades after their invention.

b40d-48b2-979e 2 hours ago | parent | prev | next [-]

This is what PowerShell does, it has both the archaic `for` style with a newer iterator-like `foreach`.

rbanffy 3 hours ago | parent | prev [-]

I would say Python really wants to look as much not-C as it can. In this case it's not the word "for" but the "for x in" construct.

Martinussen 4 hours ago | parent | prev | next [-]

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.

tialaramex 4 hours ago | parent | prev | next [-]

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.

kevinmgranger 4 hours ago | parent | prev | next [-]

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.

tialaramex 3 hours ago | parent [-]

More specifically for x in y consumes y in Rust.

https://doc.rust-lang.org/std/keyword.for.html explains how a loop is de-sugared

https://rust.godbolt.org/z/5jzhxYM51

... shows that today ranges like 0..5 aren't Copy even if that would be possible, which means if they're consumed they're gone, whereas an array of integers is Copy and so consuming it doesn't mean it's gone, you can just consume it again.

The desire is that Rust 2027 edition will change the nice syntax for ranges to produce new ranges like core::ranges::Range which are Copy if possible and only IntoIterator, the original ranges are never Copy but are Iterator, we now regret this choice.

saghm 3 hours ago | parent | prev [-]

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.