Live data from Hacker News

The humble for loop in Rust

blog.startifact.com

1–10 of 60 posts

Re: The humble for loop in Rust

#4
> 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_map`, you can spot pcmpeqd, movdqu, and psubd, while `using_loop` doesn't have any of these.

Re: The humble for loop in Rust

#5
I would have liked to see a comparison in the fold() section that functions the same way as the original for loop:

    list_of_lists.into_iter().fold(Vec::new(), 
        |mut accumulator, list| {
            accumulator.extend(list);
            accumulator
        }
    )

Re: The humble for loop in Rust

#6
post #4

> 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…

Ah thanks! I was going to ask in here to see if anyone knew because the explanation about overwriting the same vector seemed pretty off base.

Never worked in Rust though so wondered if the iterator api had some weird optional notion of size that could be utilised throughout the chain.

Re: The humble for loop in Rust

#7
post #2

Anyone have examples where fold leads to easier to read code than a for loop in Rust?

I find `foo.iter().map(|x| x.bar()).collect()` almost always easier to read and better at expressing intent than a for loop.

The other direction is more interesting to me: Those are the awkward cases where people sometimes overdo it with the functional iterator heavy style.

Re: The humble for loop in Rust

#8
post #2

Anyone have examples where fold leads to easier to read code than a for loop in Rust?

I have used fold for converting strings to a bitset in advent of code

    let string = "ewfsan";
    let bitset = string.bytes().fold(0u32 |acc, ch| acc | 1 
This is a idiom that I have used many times so this being more consice than a for loop is a plus

Of course if you have never seen a syntax before it will make less sense that anything you have seen before

Re: The humble for loop in Rust

#9
post #6
post #4

> 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…

Ah thanks! I was going to ask in here to see if anyone knew because the explanation about overwriting the same vector seemed pretty off base. Never worked in Rust though so wondered if the iterator api had some weird optional notion of size that could be utilised throughout the chain.

> Never worked in Rust though so wondered if the iterator api had some weird optional notion of size that could be utilised throughout the chain.

Fwiw, this does exist: [Iterator::size_hint] (https://doc.rust-lang.org/std/iter/trait.Iterator.html#metho...)

Re: The humble for loop in Rust

#10
post #9
post #6

Earlier quoted context omitted.

Ah thanks! I was going to ask in here to see if anyone knew because the explanation about overwriting the same vector seemed pretty off base. Never worked in Rust though so wondered if the iterator api had some weird optional notion of size that could be utilised throughout the chain.

> Never worked in Rust though so wondered if the iterator api had some weird optional notion of size that could be utilised throughout the chain. Fwiw, this does exist: [Iterator::size_hint] ( https://doc.rust-lang.org/std/iter/trait.Iterator.html#metho... )

It seems `map` should have less restrictive semantics (specifically ordering) than `for`, does that allow more optimization? I don't know much about Rust internals.
Post reply on HN