Carbon provides three operators to support logical operations on bool
values:
and
provides a logical AND operation.x and y
evaluates totrue
if both operands aretrue
.
or
provides a logical OR operation.x or y
evaluates totrue
if either operand istrue
.
not
provides a logical NOT operation.not x
evaluates totrue
if the operand isfalse
.
and
and or
are infix binary operators, and use
short-circuit evaluation.
not
is a prefix unary operator.
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)) {
...
}
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) {
...
}
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 ofand
,or
, ornot
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 abool
type), that extension point will also apply toand
,or
, andnot
.
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.
- Use punctuation spelling for all three operators
- Precedence of AND versus OR
- Precedence of NOT
- Punctuation form of NOT
- Two forms of NOT
- Repeated NOT
- AND and OR produce the decisive value
- Proposal #680: And, or, not.
- Proposal #702: Comparison operators.