Logical operators

Table of contents

Overview

Carbon provides three operators to support logical operations on bool values:

  • and provides a logical AND operation.
    • x and y evaluates to true if both operands are true.
  • or provides a logical OR operation.
    • x or y evaluates to true if either operand is true.
  • not provides a logical NOT operation.
    • not x evaluates to true if the operand is false.

and and or are infix binary operators, and use short-circuit evaluation. not is a prefix unary operator.

Details

Precedence

and and or have very low precedence. When an expression appearing as the condition of an if uses these operators unparenthesized, they are always the lowest precedence operators in that expression.

These operators permit any reasonable operator that might be used to form a bool value as a subexpression. In particular, comparison operators such as < and == have higher precedence than and and or. However, the precedence of and and or is not directly comparable with each other, so they cannot both be used directly in an expression without parentheses.

not is higher precedence than and and or, but its precedence is incomparable with most other operators, including comparison operators.

For example:

// ✅ Valid: `and` is lower precedence than the `<` or `==` operators.
if (n + m == 3 and not n < m) {
  ...
}
// The above is equivalent to:
if (((n + m) == 3) and (not (n < m))) {
  ...
}

// ❌ Invalid: `and` and `or` precedence is incomparable.
if (cond1 and cond2 or cond3) {
  ...
}
// ✅ Valid: Parentheses avoid the precedence check.
if (cond1 and (cond2 or cond3)) {
  ...
}

// ❌  Invalid: `not` precedence is incomparable with `==`.
if (not cond1 == cond2) {
  ...
}
// ❌  Invalid: `not` precedence is incomparable with `==`.
if (cond1 == not cond2) {
  ...
}
// ✅ Valid: Parentheses avoid the precedence check.
if (cond1 == (not cond2)) {
  ...
}

Associativity

and and or are left-associative. A not expression cannot be the operand of another not expression; not not b is an error without parentheses.

// ✅ Valid: `and` is left-associative, and precedence is fine.
if (not a and not b and not c) {
  ...
}
// The above is equivalent to:
if ((not a) and ((not b) and (not c))) {
  ...
}
// ✅ Valid: Parentheses avoid the `not` associativity error.
if (not (not a)) {
  ...
}

// ❌ Invalid: `not not` associativity requires parentheses.
if (not not a) {
  ...
}

Conversions

TODO: This should be addressed through a standard bool conversion design.

The operand of and, or, or not is converted to a bool value in the same way as the condition of an if statement. In particular:

  • If we decide that certain values, such as pointers or integers, should not be usable as the condition of an if without an explicit comparison against null or zero, then those values will also not be usable as the operand of and, or, or not without an explicit comparison.
  • If an extension point is provided to determine how to branch on the truth of a value in an if (such as by supplying a conversion to a bool type), that extension point will also apply to and, or, and not.

Overloading

The logical operators and, or, and not are not overloadable. As noted above, any mechanism that allows types to customize how if treats them will also customize how and, or, and not treats them.

Alternatives considered

References