23 ms·
From the first few graphs: > Rust has a nice pretty syntax for iterating: for x in &mut something { *x = (*x) * 2; } > EXCEPT when you need t
by mustache_kimono 4y ago
From the first few graphs:
> Rust has a nice pretty syntax for iterating:
for x in &mut something {
*x = (*x) * 2;
}
> EXCEPT when you need to do anything else to the iterator, then its ugly:
for (i, x) in something.iter_mut().filter(|| {...}).enumerate() {
*x = (*x) * i
}
This is just so goofy. Who writes Rust like this? Wouldn't everyone write:
something
.iter_mut()
.filter(|| {...})
.enumerate()
.for_each(|(i, x)|) {
*x = (*x) * i
});
> There should be one -- and preferably only one --obvious way to do it.
Overhead-wise, you can't expect everyone to take to the iterator model right away. Sometimes you want a for loop, or you want a for loop for right now.
I think Rust being multi-paradigm is a strength, with the understanding that the preferred approach/model is the more functional, more immutable iterator model for 95% of your use cases.
> Again, the absolute lack of composability is astounding. Whats the point of even having iterator methods if you can't use them for real world usecases, where code is regularly fallable, so you need to return a Result.
You can, you just haven't figured out how yet. This is frustrating, but, gosh, you'll learn how sooner or later.
let y: Result<Vec<_>> = iterator.map(|x| {
x.some_fallible_method()
}).collect();
- duped 4y agoEdit: this is totally wrong No, because that doesn't evaluate the iterator. let it = something .iter_mut() .filter(|item| ...) .enumerate(); for (i, x) in it { ... }
- proto_lambda 4y agoBoth for_each() and collect() into a Vec exhaust the iterator.
- sophacles 4y agoI write `for x in some.iter().built().up().like().this()` a lot. I think of the iterator building as mapping values from an iterator to values to consume - the for loop consumes them. for_each with side-effects just confuses me later in a lot of those cases - it has it's place but so do for loops. (also, closure issues around variable capture, moves, etc come into play with for_each).
- mustache_kimono 4y agoMostly agree with the points made in your comment, but I think the complaint of the article is "What's the point of having the 'pretty' syntax if it only works in the simplest of cases?" If this is your concern, and you really must write it like that, I'd break it up, into your iter and your loop. let y_iter = some.iter().built().up().like().this(); for x in y_iter { ... }
- tomjakubowski 4y agoyeah you can often come up with a good descriptive name for that y_iter too, like `selected_widgets`
- chrismorgan 4y ago> This is just so goofy. Who writes Rust like this? Wouldn't everyone write: something.iter_mut().…().for_each(|(i, x)|) { … }) No. As a user for just short of a decade, I have probably used .for_each() less than a dozen times in total (grep over the current state of most of the code I’ve ever written: three matches). I know it’s there, but it doesn’t often feel right, and I have certainly regularly used for loops where closure capture rules mean that I couldn’t have used .for_each(), which is strictly less expressive. Perhaps if I had come from a language like Ruby I might use it more, but I came more from Python and JavaScript. I don’t think the article showed a good formatting, however; I’d write it more like this: for (i, x) in something .iter_mut() .filter(|| {...}) .enumerate() { *x = (*x) * i; }
- mustache_kimono 4y ago> I know it’s there, but it doesn’t often feel right, and I have certainly regularly used for loops where closure capture rules mean that I couldn’t have used .for_each(), which is strictly less expressive. I think this is fine. I think Rust's strength is as a multi-paradigm language. I would say for this specific code, a for_each() makes more sense than the alternatives (on the margin), but for more complex use cases, where something like a try_for_each() might be used, where you may need to return 3 different error types, which for some reason one type can't be easily coerced out of the closure, a for loop makes tons of sense. But I think that's a 5% use case, and in the other 95% of cases the iterator approach is to be preferred. For many sound technical reasons, as well as for more squishy code readability reasons (maps and folds and filters are simply more readable to my eye). Again I strictly don't have a problem with anything in your comment, or anyone using for loops, but if I was writing your for loop and my concern was the author's re: pretty syntax, I'd write it as: let y_iter = some.iter().built().up().like().this(); for x in y_iter { ... }