if (a < 0) true else false is an expression, it returns a boolean. if (a < 0) true else false; is an invalid statement in zig since it is an expression that returns a value and values cannot be implicitly discarded. To make it valid statement, it can be changed to explicitly discard the value: _ = if (a < 0) true else false;. A statement requires some sort of operation to occur, often an assignment.
In addition to what @desttinghim writes, the flexibility that Zigâs if allows can make this topic even more confusing. In Zig, if you want to use if as an expression, you cannot use the curly braces around the branches and the else branch is mandatory:
const below_zero = if (a < 0) true else false; // OK
const below_zero = if (a < 0)
true
else
false; // OK
const below_zero = if (a < 0) { true } else {false }; // error
const below_zero = if (a < 0) true; // error
const below_zero = if (a < 0) { true }; // error
const below_zero = if (a < 0) true else 13; // error, must produce same type
An if with the curly braces around the branches is not an expression, itâs a statement. Like function bodies, thereâs no semicolon after the closing brace. The else branch is optional.
if (a < 0) {
print("Below zero!\n", .{});
}
if (a < 0) {
print("Below zero!\n", .{});
} else {
print("Above zero!\n", .{});
}
What can be a little confusing is when you mix in labeled blocks, which you can use in an if expression, making it look like an if statement with curly braces:
const below_zero = if (a < 0) blk: {
break :blk true;
} else blk: {
break blk: false;
};
But even so, the labels are pretty easy to spot, enough to differentiate this from an if statement.
$ /opt/zig-0.11/zig run if.zig
if.zig:6:35: error: expected ')', found ';'
if (if (t < 0) true else false;)
It does not have a value, but we can assign this nonexistent value to a var.
Ok, we are assigning the value of if (t < 0) true else false.
Does that mean that ';' is a terminator for '='?!?!?
The ; terminates a statement, and in Zig, an assignment using the = operator is a statement. Note that in other languages, = is an expression like in:
a = b = c;
But this has led to bugs when you mistakenly use = when you meant ==. So most new langueges donât treat = assignment as an expression any more. The same has happened with the ++ and -- operators. In ancient (lol) languages, these are expressions:
a = c++;
a = ++c;
But once again, this has led to much confusion and bugs when the programmer is not clear on what the actual value being returned is. In Go, they have postfix ++ and -- only and they are not expressions to avoid this confusion. In zig, theyâre simply not included at all and you have to use += or -= which are not expressions either.
So back to if, I guess itâs hard to put it in a single category in Zig, given it can serve as an expression and a statement. The same is true for while, for, and switch which all have expression and statement forms.
Right. So to put it in the most fundamental way, in Zig all statements must end with ; and expresiions by themselves are not statements, so thatâs why your example code if (a < 0) true else false; is not valid Zig code (as @desttinghim pointed out above.)
There are languages that allow expression statements like a + b;, but not Zig. In Zig the value returned from an expression must be used and cannot be ignored. Even discarding it with _ = a + b; counts as using the value.
A function always returns a value, and in the case of void, thatâs the only value the language allows you to ignore.
A function with return type void actually doesnât return any value.
Given that in Zig there is an actual noreturn return type, I was inclined to believe option 1 was the case. Also, when return is followed by something, it has to be the value to return, so it does seem that a call to a void function returns a void value given this:
A term missing from this discussion is âside-effectâ. In general, statements have side-effects, meaning they cause changes to the environment, whereas expressions do not. The expression a + b doesnât change anything. The statement c = a + b; does. Whatever stored in c previously is lost forever, replaced by the outcome of the addition expression.
Assignment to variables is the most common side-effect. Thereâre also operations like printing to the screen or outputting to a network connection.
Expressions can have side-effects, but thatâs something we try to avoid since they make a program harder to understand. Obviously, programming with the use of variables is not very practical. We do try our best to isolate the side-effects, either within a function scope or within an object.