AFAIK it is an invalid code nowadays. How was it working then?
What is the syntax trick when I pass lambda right after calling iter?
Is it syntax still working for any use case?
The linked archive page is from 2011. Rust only release its first stable release, version 1.0, in 2015. Since then, the language remains syntactically unchanged, and all old syntax keeps working, with the caveat of some minor syntactic changes that are opt-in via the “editions” mechanisms (so those won’t break your code, and they won’t split the ecosystem, but allow further syntax changes past 1.0).
Before Rust 1.0, as far as I know, the language syntax and libraries used to change regularly, and significantly, so it’s no surprise that this code example is invalid today. Though I’m not actually familiar with the Rust syntax at that point, my best guess as for the equivalent code today would be something like
fn main() {
for i in vec![1, 2, 3] {
println!("hello, {i}");
}
}
though I’m not entirely sure how much of today’s ownership system existed at the time, or whether the language was perhaps relying more on garbage collection and shared values at the time, so a direct translation might be impossible, or leaves room for multiple alternative approaches, depending on how you look at it.
This code is from a time so long ago that iterators, as we know them today, didn't actually exist in Rust. Back then, IIRC, for loops over iterators didn't exist, because you passed the closure to run to the iterator, and it ran it for each value.
Here's my attempt at a direct translation to modern rust:
By the way, whilst the code example you gave seems to be from Rust 0.2, on from 0.3, I’m able to find online documentation still hosted today under links such as https://doc.rust-lang.org/0.3/rust.html -- for the reference https://doc.rust-lang.org/0.3/tutorial.html -- for a tutorial https://doc.rust-lang.org/0.3/core/ -- the core library https://doc.rust-lang.org/0.3/std/ -- the standard library
… and possibly more, so you can explore those without needing to use the archive.org mirrors; but it’s a bit hard to find out what links I’m possibly missing, without any “main” page I know of.
These kinds of links seem to work for various versions.
For pre-1.0 versions of Rust, you can find a lot of information in doc/tutorial.md or src/doc/tutorial.md. See, e.g., closures in 0.2 vs. 0.3. The original closure syntax was copied from Ruby, but it was later changed to no longer require braces surrounding the argument list and body (commit).
The special closure-based for loop syntax (mirroring the do syntax) was documented in doc/tutorial.md until 0.7, where it was moved to doc/tutorial-container.md. Closure-based for loops were finally replaced with iterator-based for loops by 0.8 (PR), using the familiar for x in y {} syntax we know today. (They were called foreach loops for a brief period while the old for loops were still being phased out.) Meanwhile, do syntax was removed by 0.10 (RFC, PR), since it had caused somewhat of a syntax confusion between stack closures and heap closures (which today are simply boxed closures).
One post-1.0 syntax change to be aware of is that one used to just write Trait instead of dyn Trait for trait objects. Are you talking about the trait or the type? Completely contextual; is the grammar expecting a type or a trait?
(One should be aware of this when reading RFCs for example, as many foundational RFCs were written before dyn Trait was a thing.)
As we are talking about RFCs already, here’s the relevant RFC introducing the “dyn Trait” syntax itself. So feel free to take a look for clarification
Besides listing reasons and context the relevant part for explaining the simply the meaning of dyn Trait is this section: