Inquiry about 'for' loop syntax when using references

The two are not always equivalent. For example, in the following program,
the whole array a is copied in the first loop (kind of implicitly).

const std = @import("std");

pub fn main() !void {
	var a: [3]u8 = .{0} ** 3;
	
	for (a, 0..) |v, i| {
		a[1] = 2;
		std.debug.print("{}: {}\n", .{i, v});
	}
	// 0 0 0
	
	a[1] = 0;
	for (&a, 0..) |v, i| {
		a[1] = 2;
		std.debug.print("{}: {}\n", .{i, v});
	}
	// 0 2 0
}

Some people indeed get confused here. So I prefer to disable iterating arrays.
If an array has to be copied, we can do it explicitly:

	const aCopy = a;
	for (&aCopy, 0..) |v, i| {
		a[1] = 2;
		std.debug.print("{}: {}\n", .{i, v});
	}
1 Like

I tend to think you use the & when you want to mutate and the |*slot| when you want to write to the slot. And maybe I’ve just gotten used to this stuff but if I was iterating over a AND mutating it with a[i], I would pay closer attention than usual that I know exactly what I’m specifying. And I might even just switch to a while loop if I feel like the for-construct is too magical for me.

2 Likes