const expect = @import("std").testing.expect; test "for basics" { const items = [_]i32{ 4, 5, 3, 4, 0 }; var sum: i32 = 0; // For loops iterate over slices and arrays. for (items) |value| { // Break and continue are supported. if (value == 0) continue; sum += value; } expect(sum == 16); // To iterate over a portion of a slice, reslice. for (items[0..1]) |value| sum += value; expect(sum == 20); // To access the index of iteration, specify a second capture value. // This is zero-indexed. var sum2: i32 = 0; for (items) |value, i| { expect(@TypeOf(i) == usize); sum2 += @intCast(i32, i); } expect(sum2 == 10); } test "for reference" { var items = [_]i32{ 3, 4, 2 }; // Iterate over the slice by reference by // specifying that the capture value is a pointer. for (items) |*value| value.* += 1; expect(items[0] == 4); expect(items[1] == 5); expect(items[2] == 3); } test "for else" { // For allows an else attached to it, the same as a while loop. var items = [_]?i32{ 3, 4, null, 5 }; // For loops can also be used as expressions. // Similar to while loops, when you break from a for loop, // the else branch is not evaluated. var sum: i32 = 0; const result = for (items) |value| { if (value != null) sum += value.?; } else blk: { expect(sum == 12); break :blk sum; }; expect(result == 12); } test "nested break" { var count: usize = 0; outer: for ([_]i32{ 1, 2, 3, 4, 5 }) |_| { for ([_]i32{ 1, 2, 3, 4, 5 }) |_| { count += 1; break :outer; } } expect(count == 1); } test "nested continue" { var count: usize = 0; outer: for ([_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }) |_| { for ([_]i32{ 1, 2, 3, 4, 5 }) |_| { count += 1; continue :outer; } } expect(count == 8); } fn typeNameLength(comptime T: type) usize { return @typeName(T).len; } test "inline for loop" { var sum: usize = 0; inline for ([_]i32{ 2, 4, 6 }) |i| { const T = switch (i) { 2 => f32, 4 => i8, 6 => bool, else => unreachable, }; sum += typeNameLength(T); } expect(sum == 9); }