3 ms·
This is a pretty low quality rant. Going example by example: for (i, x) in something.iter_mut().filter(|| {...}).enumerate() { *x = (*x) * i }
by justinpombrio 4y ago
This is a pretty low quality rant. Going example by example:
for (i, x) in something.iter_mut().filter(|| {...}).enumerate() {
*x = (*x) * i
}
you can this this in loop style if you want:
for i in range(something.len()) {
let x = &mut something[i];
if ... {
*x = (*x) * i;
}
}
or if you prefer, in iter style:
something
.iter_mut()
.filter(|| {...})
.enumerate()
.for_each(|(x, i)| *x = (*x) * i);
The next two examples can be written:
let res: Vec<_> = iterator.iter().filter_map(|x| x.foo()).collect();
let z = x.foo().and_then(|y| y.bar());
There is an ergonomics issue around the fact that if you stick `?` or `.await()` in a closure, it returns to that closure instead of the function containing it. But the way this issue manifests itself is the standard library having a pile of different variations on methods, like `.map()` vs. `.filter_map()`. That's the thing to complain about, not the fact that closures work the same way they do in every other language.
- Pxtl 4y agoI've never used Rust - in a conventional language you'd just have a mutable variable defined outside of the loop and used and incremented inside of the loop. I assume Rust's for-loops can't access the outside variable scope that way? Like (pseudocode) var i = 0 for(item in items) { item.DoThing(i) i+=1 } Does rust not allow that kind of mutation and access of a variable from outside the loop within the loop?
- holmium 4y agoyou can do it that way if you wanted to let mut i = 0; for item in items { item.method(i); i += 1; } I don't know why you'd it that way, but Rust definitely isn't stopping you from doing that. e: and as running example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021 https://play.rust-lang.org/?version=stable&mode=debug&editio...
- Pxtl 4y agoWell, the complaint in the article is that the idiomatic way is kind of inscrutable. I'm more than willing to let pragmatism win in those cases, since so many languages make this pattern a nuisance instead of providing a simple "enumerate this array with index" out-of-the-box as part of the standard library. IIRC you have to roll your own in Java, C#, and Powershell.
- lostmsu 4y agoIn C# there's a .Select overload, that gives your lambda both item and its index.
- apendleton 4y agoNo, you definitely can. You generally can't mutate things that would cause the iterator itself to be invalidated (like, you can't delete items from a vector while you're iterating over it), but you can get an iterator over a vector that gives you a mutable reference to each of its members, which would be sufficient to do what you're suggesting here. I think what they were pointing out (and I agree with) is that the mixing of combinators and imperative-style for loops that's going on in the post doesn't feel very natural. Typically if you would _either_ do blah .into_iter() .filter(|x| x.some_condition()) .for_each(|x| x.do_something()); or for x in blah { if !x.some_condition() { continue; } x.do_something(); } But `for x in blah.into_iter().filter(...` is a bit unusual.
- butt_____hugger 4y agoYou could definitely do that with Rust, but using `enumerate` rather than mutable variables is considered idiomatic. Neither is more or less "conventional". lol 3 people said the same thing at the same time. rust strike force assemble
- holmium 4y agohaha yes the discourse level thread is like perfect for all us "we've read the Book" people to comment on.
- deleted 4y ago[deleted]
- nu11ptr 4y agoSure, you can do something like that, but it is unnecessary. Like Python, you can use "enumerate" to give you a tuple that that will give you `i` automatically. https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=59c845d8ba631cf0e0e84df3c34d20f2 https://play.rust-lang.org/?version=stable&mode=debug&editio... struct Item(u32); impl Item { fn do_thing(&self, i: usize) { println!("The value of `i` is: {i}"); } } fn main() { let items = vec![Item(1), Item(2), Item(3)]; for (i, item) in items.iter().enumerate() { item.do_thing(i); } }
- sophacles 4y agoThis works fine in rust too. Iterators are a place where the power of the type system (etc) feel like magic and so you'll find a tendency for solving things with the magic (especially in newer programmers, but everyone does it at least a little). Compare all the crazy things people build out of channels in go, or a similar tendency in python to over-do the generator expressions.