(you can find previous post about same topic here)
Comparing the loop syntax in Go and Zig, it's clear that the latter offers some additional possibilities in terms of expression and clarity about what's happening. Zig provides two keywords while and for, while in Go everything is solved with for.
As in previous posts, I'll try to present two scripts that achieve the same result, in this case starting from an array of 10 integers.
while loop
// Zig
const items = [10]i8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var i: usize = 0;
std.debug.print("--- basic while\n", .{});
while (i < items.len) {
std.debug.print("index {d}: item {d}\n", .{ i, items[i] });
i += 1;
}
i = 0;
std.debug.print("--- while with increment expression and continue\n", .{});
while (i < items.len) : (i += 1) {
// increment expression is calculated as part of continue
if (i % 2 == 0) continue;
std.debug.print("index {d}: item {d}\n", .{ i, items[i] });
}
In Go there is no while for looping, but you can achieve it with a for with only the condition. The example with continue could be solved in better ways, but it's presented this way to highlight the disadvantage of not having the separate expression as Zig offers.
// Go
items := [10]int8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
i := 0
fmt.Println("--- condition-only for loop (while style)")
for i < len(items) {
fmt.Printf("index %d: item %d\n", i, items[i])
i += 1
}
i = 0
fmt.Println("--- condition-only for loop (while style) with continue")
for i < len(items) {
if i == 5 {
i += 1
continue
}
fmt.Printf("index %d: item %d\n", i, items[i])
i += 1
}
for loop
As for the for loop, Zig uses it more as a multi-iterator: this means we can pass as many iterable objects as we want to the for loop, as long as they have the same length, or numeric ranges. If we use an open-ended numeric range, the length of the iterable will be used as the end point.
std.debug.print("--- for iterator capturing only values\n", .{});
for (items) |value| {
std.debug.print("item {d}\n", .{value});
}
std.debug.print("--- for iterator capturing value and index\n", .{});
for (items, 0..) |value, y| {
std.debug.print("index {d}: item {d}\n", .{ y, value });
}
const letters = [10]u8{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
for (items, letters, 10..) |item, letter, index| {
std.debug.print("index {d}: letter {c} - item {d}\n", .{ index, letter, item });
}
std.debug.print("--- for iterator with range only\n", .{});
for (0..(items.len / 2)) |y| {
std.debug.print("index {d}: item {d}\n", .{ y, items[y] });
}
In Go it's idiomatic to use for combined with range and extract indices and/or values
fmt.Println("--- classic for loop ")
for i = 0; i < len(items); i++ {
fmt.Printf("index %d: item %d\n", i, items[i])
}
fmt.Println("--- for loop with range, Go idiomatic ")
for z, item := range items {
fmt.Printf("index %d: item %d\n", z, item)
}
fmt.Println("--- for loop with range capturing only value")
for _, item := range items {
fmt.Printf("only item %d\n", item)
}
fmt.Println("--- for loop with range capturing only index")
for z := range items {
fmt.Printf("only index %d\n", z)
}
Mutating values while looping
In both Zig and Go it's not possible to directly mutate captured values since they are copies. In Zig this is explicit because the captured value is a const, so any modification is blocked at compile time; in Go it's not obvious and must be verified by running the program. Let's see how to handle mutation during the loop in each language.
// declared as var so items can be mutated
var mitems = [10]i8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std.debug.print("--- for iterator with value mutation\n", .{});
// point to array and use pointer to value
for (&mitems) |*value| {
// dereference the pointer to mutate value
value.* *= 2;
}
for (mitems, 0..) |value, y| {
std.debug.print("index {d}: item doubled {d}\n", .{ y, value });
}
mitems := [10]int8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("--- for loop with mutation")
for z := range mitems {
// use index and not captured value
mitems[z] *= 2
}
for z, item := range mitems {
fmt.Printf("index %d: item doubled %d\n", z, item)
}
Top comments (0)