News for hackers. Stuff that matters.
Re:Rust – A hard decision pays off by throwaway894345 on Wednesday August 24, 2022 @12:45PM (#32582081)
Hah, it took me and a bunch of other people in the Rust discord a fair amount of time to figure out how to get the first example to compile correctly in the first place, and I find the “transpose()” business to be particularly convoluted. I think even Rust people would prefer the imperative version. I also suspect there’s some hindsight benefit at play in that it’s easier to make sense of the first snippet than it was to write it.
Re:Rust – A hard decision pays off by tialaramex on Wednesday August 24, 2022 @01:06PM (#32582461)
Yes, the imperative version looks like the sane choice to me. Rust's iterator documentation does suggest that this is not a language which favours iterator chains everywhere.

However one reason to prefer an iterator chain in some cases is that the chain might imply an optimisation you'd otherwise have to write manually and might not think of.

For example if I have N things, and I map them, perhaps more than once, but I'm definitely getting N of whatever the output of the last map was, the iterator chain might very well see that I don't actually have any way to change N and so when I collect() that into a Vec the Vec it gives me is constructed with capacity N, saving the (amortized but non-zero) cost of growing it during insertions.

Imperatively I can remember to write Vec::with_capacity(N), and that's safe of course but it's an extra step to remember.

The imperative approach does particularly shine on the opposite edge of this, if I know that I'm getting no more than 100 items out of this pipeline, despite putting N in, Rust almost certainly won't see that and won't make Vec::with_capacity(100) for a collect() call whereas my imperative code can just explicitly write Vec::with_capacity(100) or whatever.

Re:Rust – A hard decision pays off by sgeisenh on Wednesday August 24, 2022 @01:35PM (#32582872)
Depending on how you write it, iterators are much better at this since most iterator methods produce iterators with size hints.

If you use "take" for example, collect should do the right thing: https://doc.rust-lang.org/src/core/iter/adapters/take.rs.htm...

Re:Rust – A hard decision pays off by tialaramex on Wednesday August 24, 2022 @02:08PM (#32583425)
Mere hints aren't enough for collect()

It will only care about your hints if you implement the unsafe trait TrustedLen (which promises those hints are correct)

Take is indeed TrustedLen if the Iterator it's taking from is TrustedLen (as in this case it can be sure of the size hint)

If you get to ~100 via some means other than take()ing 100 of them, chances are you don't have TrustedLen as a result.

Re:Rust – A hard decision pays off by Alexendoo on Wednesday August 24, 2022 @02:55PM (#32584077)
TrustedLen will mean it can safely take the upper bound, but Vec for example will still use the lower bound of the hint when something isn't TrustedLen

https://doc.rust-lang.org/src/alloc/vec/spec_from_iter_neste...

Re:Rust – A hard decision pays off by tialaramex on Wednesday August 24, 2022 @03:14PM (#32584353)
Ooh nice, I hadn't seen that. OK, so there are probably places where I assumed the iterator won't do as nice a job of collect() as I did manually but I was wrong.

I wonder how the hell I didn't see that when I was tracking down how collect() ends up caring about TrustedLen.

Thanks.

Re:Rust – A hard decision pays off by ywei3410 on Wednesday August 24, 2022 @01:08PM (#32582471)
Honestly the closure + `transpose` is really ugly as sin. I had to do a double take and reason through the steps which you took to get that particular snippet (while not reading the imperative one).
Re:Rust – A hard decision pays off by throwaway894345 on Wednesday August 24, 2022 @03:28PM (#32584542)
Thanks, I feel validated. (: