Earlier quoted context omitted.
That surprises me, and I'd expect the FP version to be at least as fast, with the option to be much faster. With the for loop, you're saying "run against this value, then run against the next one, then run against the next one, then...". If the compiler isn't certain that the iterations aren't free of side effects, then it would have to run each one in order before moving on to the next. `.map(...)` implies "I don't…
> `.map(...)` implies "I don't care about ordering, and therefore you don't need to, either" In plenty of languages, no such implication exist. `map` can be specified to run in a certain order.
The humble for loop in Rust
41–50 of 60 posts
Re: The humble for loop in Rust
#42> Why is map so much faster? I am not sure. I suspect with the map() option the Rust compiler figures out it can avoid allocations altogether by simply writing over the original vector, while with the loop it can't. Or maybe it's using SIMD? I tried to look in the compiler explorer but I'm not competent enough yet to figure it out. Maybe someone else can explain! Yep, it's due to SIMD -- in the assembly for `using_ma…
SIMD is true, but the original guess is correct, and that effect is bigger! using_map is faster because it's not allocating: it's re-using the input array. That is, it is operating on the input `v` value in place, equivalent to this: pub fn using_map(mut v: Vec ) -> Vec { v.iter_mut().for_each(|c| *c += 1); v } This is a particularly fancy optimization that Rust can perform.
Re: The humble for loop in Rust
#43Yeah I kind of wish there was a way to still use `?` inside map/filter/etc. lambdas. Error handling with that functional style is generally way more awkward than for loops, but also it's often more elegant in other ways (e.g. Rayon). I think Ruby has some kind of feature that works like that but IIRC it looked less foot-gun more foot-bazooka. Does anyone know of any languages that solve that problem elegantly?
Re: The humble for loop in Rust
#44Earlier quoted context omitted.
That surprises me, and I'd expect the FP version to be at least as fast, with the option to be much faster. With the for loop, you're saying "run against this value, then run against the next one, then run against the next one, then...". If the compiler isn't certain that the iterations aren't free of side effects, then it would have to run each one in order before moving on to the next. `.map(...)` implies "I don't…
> `.map(...)` implies "I don't care about ordering, and therefore you don't need to, either" In plenty of languages, no such implication exist. `map` can be specified to run in a certain order.
Re: The humble for loop in Rust
#45Earlier quoted context omitted.
Streams (FP in java) is slower than for loops for a couple reasons. A big one is java doesn't natively support real closures or lambdas. It does have syntax for them, but that is just syntactic sugar for an class with a single method under the hood. So streams end up doing lot of object allocation and garbage for the fake closures. Also, streams operate on objects, so they have to be on the heap. You can't use them w…
Huh, interesting. Thanks for that! Today, I learned.
Re: The humble for loop in Rust
#461. The comparisons, as you've written them up, probably will get stale fast. It would be nice to be able to re-run them.
2. Some of the examples are surprising. Why? Any bugs? Some kind of weirdness? Readers would want to explore.
3. Readers can see how you did the benchmarks. We can put more/less stock in them. Hopefully you used `criterion` or similar, with warm ups, etc.
Re: The humble for loop in Rust
#47Earlier quoted context omitted.
> `.map(...)` implies "I don't care about ordering, and therefore you don't need to, either" In plenty of languages, no such implication exist. `map` can be specified to run in a certain order.
What languages would that be?
C# and Javascript are the ones that I know of for sure.
Re: The humble for loop in Rust
#48Yeah I kind of wish there was a way to still use `?` inside map/filter/etc. lambdas. Error handling with that functional style is generally way more awkward than for loops, but also it's often more elegant in other ways (e.g. Rayon). I think Ruby has some kind of feature that works like that but IIRC it looked less foot-gun more foot-bazooka. Does anyone know of any languages that solve that problem elegantly?
What's the ruby feature you're referring to?
Re: The humble for loop in Rust
#49Earlier quoted context omitted.
That surprises me, and I'd expect the FP version to be at least as fast, with the option to be much faster. With the for loop, you're saying "run against this value, then run against the next one, then run against the next one, then...". If the compiler isn't certain that the iterations aren't free of side effects, then it would have to run each one in order before moving on to the next. `.map(...)` implies "I don't…
Streams (FP in java) is slower than for loops for a couple reasons. A big one is java doesn't natively support real closures or lambdas. It does have syntax for them, but that is just syntactic sugar for an class with a single method under the hood. So streams end up doing lot of object allocation and garbage for the fake closures. Also, streams operate on objects, so they have to be on the heap. You can't use them w…
In Rust a closure is really just a struct that implements up to three closure traits, each of which provide a single function. So from that side of things, what Java is doing for them isn't inherently different from Rust.
Re: The humble for loop in Rust
#50Earlier quoted context omitted.
That surprises me, and I'd expect the FP version to be at least as fast, with the option to be much faster. With the for loop, you're saying "run against this value, then run against the next one, then run against the next one, then...". If the compiler isn't certain that the iterations aren't free of side effects, then it would have to run each one in order before moving on to the next. `.map(...)` implies "I don't…
Streams (FP in java) is slower than for loops for a couple reasons. A big one is java doesn't natively support real closures or lambdas. It does have syntax for them, but that is just syntactic sugar for an class with a single method under the hood. So streams end up doing lot of object allocation and garbage for the fake closures. Also, streams operate on objects, so they have to be on the heap. You can't use them w…
Sometimes, if the Java JIT manages to inline absolutely everything, it can optimize away these overheads. But in practice, Rust FP gets optimized a lot more reliably than Java FP.