Logical

The logical operators combine and invert bool values.

OperatorOperationResultLevel
!nottrue when the operand is false16
&&andtrue when both operands are true6
||ortrue when either operand is true5
let isReady = true;
let hasWork = false;
PrintLine("{} {} {}", isReady && hasWork, isReady || hasWork, !isReady);

This prints false true false.

bool operands only

Every operand must be a bool. A number, a pointer or an optional is never treated as true or false; write the comparison you mean:

let count: int32 = 3;
let zero = !count;
let both = count && true;
error: operator '!' requires a bool operand, but found 'int32'
error: operator '&&' requires a bool left operand, but found 'int32'

Write count == 0 and count != 0 && true. The same rule applies to the conditions of if, while and the conditional operator.

Short-circuit evaluation

&& and || evaluate their left operand first and evaluate the right one only when it can still change the answer:

ExpressionThe right side runs when
left && rightleft is true
left || rightleft is false

That makes it safe to guard a test with another one:

if index < values.length && values[index] == target {
    PrintLine("found");
}

values[index] is read only after the bounds test has passed. A call on the right side is skipped the same way:

let a = Check("left", false) && Check("right", true);

Only left is checked; Check("right", true) never runs.

Precedence

! is a prefix operator, so it applies only to the operand right after it: !ready && busy is (!ready) && busy, and !count == 0 is (!count) == 0. Negate a larger expression by wrapping it, !(ready && busy).

&& binds more tightly than ||, the way * binds more tightly than +:

PrintLine("{}", true || false && false);

This is true || (false && false), which prints true. Both bind more loosely than every comparison, so comparisons combine without parentheses.

Non-short-circuiting forms

The bitwise operators &, |, ^ and ~ also accept bool operands. & and | compute the same answer as && and ||, but always evaluate both sides, and ^ is exclusive or:

let c = Check("left", false) & Check("right", true);
PrintLine("{}", true ^ true);

Both checks run here. Use && and || for conditions, and & or | only when the right side must run for its effect.

See also