Array

#296 Aug 2026

296. [T; N]::each_ref — Map Over an Array Without Giving It Away

arr.map(f) consumes the array — one call and your data is gone. each_ref() turns [T; N] into [&T; N], so you can map over borrows and keep the original.

Bite 118 showed [T; N]::map — transform an array, stay allocation-free. But it takes the array by value. With non-Copy elements, the array is gone after one call:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let names = [
    String::from("alpha"),
    String::from("beta"),
    String::from("gamma"),
];

let lens = names.map(|s| s.len());
println!("{names:?}");
// error[E0382]: borrow of moved value:
// `names`

each_ref (stable since 1.77) borrows every element in place, producing a [&T; N] — a fixed-size array of references, no allocation, no clone:

1
2
3
4
5
let lens = names.each_ref()
    .map(|s| s.len());

assert_eq!(lens, [5, 4, 5]);
println!("{names:?}"); // still yours

The result is a real array, so everything from bite 118 applies: the output keeps the size N in the type, and map on it can’t fail halfway.

There’s a mutable twin, each_mut, which gives [&mut T; N] — handy when you want to hand out exclusive borrows of each slot separately:

1
2
3
4
5
let mut scores = [1, 2, 3];
let [a, _, c] = scores.each_mut();
*a += 10;
*c += 30;
assert_eq!(scores, [11, 2, 33]);

Destructuring each_mut() is the clean way to get multiple &mut into one array at the same time — no split_at_mut index math, and the borrow checker sees each element as its own borrow.

Why not just names.iter().map(...).collect()? That builds a Vec — a heap allocation, and the length N is erased from the type. each_ref().map(...) stays [_; N] end to end.