PSA: iter::once can now be spelled as `[]`

This has been true for a while, but I've just realized that, as arrays are now IntoIter, there's little reason to use std::iter::once(expr), as [expr] is equivalent, shorter, and somewhat more direct.

7 Likes

Some(expr) was always (AFAIK) equivalent. The advantages of once() is better clarity and being an iterator directly and not just IntoIterator.

2 Likes

Yeah, the's Some idiom, but I avoided that as it didn't feel semantically equivalent, as Option::IntoIter can have length one or zero

1 Like

std::iter::Once can also have length zero after the first .next() call.

2 Likes

Yes, but semantically this is irrelevant. However I still prefer once() because IMHO it is more clear even than [expr].

Keep in mind that IntoIter is much bigger if you store it somewhere:

println!("{}", std::mem::size_of_val(&[true].into_iter())); // 24
println!("{}", std::mem::size_of_val(&std::iter::once(true))); // 1

This is because for arrays, their alive elements range is represented as a pair of usizes.

10 Likes

[T; 1] sometimes can be the cheapest if exact one element is needed:

size_of_val(&once(1u8)) = 2
size_of_val(&Some(1u8)) = 2
size_of_val(&[1u8]) = 1

size_of_val(&once(1u16)) = 4
size_of_val(&Some(1u16)) = 4
size_of_val(&[1u16]) = 2

size_of_val(&once(1u32)) = 8
size_of_val(&Some(1u32)) = 8
size_of_val(&[1u32]) = 4

Edit: Once<T> and Some(T) are identical in size as IntoIterator, but array is actually larger

size_of_val(&once(1u8).into_iter()) = 2
size_of_val(&Some(1u8).into_iter()) = 2
size_of_val(&[1u8].into_iter()) = 24

I'll note that [x] is IntoIterator, not Iterator, so the comparison is often to [x].into_iter() -- at which point iter::once(x) starts getting nicer again.

But to look more literally at the topic [].into_iter() also works as a replacement for iter::empty.

4 Likes