This compiles (if we declare std).
for (0..12)|i| for (i + 1..12)|j| for (j + 1..12)|k|
std.debug.print("{},{},{}\n", .{i,j,k});
This however not. It requires an extra ; after the closing brace.
for (0..12)|i| for (i + 1..12)|j| for (j + 1..12)|k| {
std.debug.print("{},{},{}\n", .{i,j,k});
} // ; needed
If we use braces for every loop (of course) not.
for (0..12)|i| {
for (i + 1..12)|j| {
for (j + 1..12)|k| {
std.debug.print("{},{},{}\n", .{i,j,k});
}
}
}
What is the idea behind it?
I think it is syntactically very strange.
1 Like
Because the inner loops become expressions which need to be terminated with ;.
an easier to understand example would be
const foo = for (0..1) |n| {
//...
} else ...; // did ya know you could have an else on a loop :3
everything after the = becomes an expression.
6 Likes
this is due to how for statements are defined in the zig grammar. There’s actually 2 variants of for, ForStatement and ForExpr, one used when it’s present as a regular statement inside a statement block, the other one where an expression is expected.
The first for loop with the (0..12)|i| parameters is a ForStatement, which can have the form for (...)|...| {} or for (...)|...| <expression>; (ignoring for ... else ... here for simplicity)
The inner for loops are ForExpr in the cases where their parent for loop is the <expression> version, even if these nested ForExpr instances have a {} body, so you still need the terminating semicolon on the top-level brace-less ForStatement
4 Likes
#1755 aims to reduce this kind of surprise.
3 Likes