if decides which code block to perform based on the truth of one or more conditional expressions. Consider:

fn abs(x i32) i32:
  mut result i32;
  if x < 0:
    result = -x
  else:
    result = x
  result

if is used by this function to correctly return the positive, absolute value of x. x < 0 is a conditional expression that evaluates to true whenever x is a negative number. When the conditional evaluates as true, the subsequent block is performed, which converts x to its positive equivalent. When the conditional is not true, the block after the else is performed instead, which captures the value of x. The else clause is optional; it need not be specified if there is no alternative action to perform when the condition is false.

if variations

Before covering the logic of conditional expressions, let's summarize various ways to use if.

if as expression

As with blocks, if can be used as an expression. This (along with implicit return) provides us with another way to write this function:

fn abs(x i32) i32:
  if x < 0:
    -x
  else:
    x

Multiple conditions

If we have more than one condition to test, each corresponding to a different block to perform, every condition after the first is preceded with elif (short for "else if"). For example:

fn abs(x i32) i32:
  if x < 0:
    -x
  elif x == 0:
    0
  else:
    x

Conditional Expressions

Conditional expressions are often just simple comparisons, as shown above. However, complex conditional expressions can be formulated that use logical operators, pattern matching, functions or methods. Let's walk through the possibilities, beginning with the basics.

True vs. False

A conditional expression must evaluate to true or false. If it does not, an attempt is made to find and use the value type's isTrue method. Several types (but not all) support this method. For example:

Equivalence

With most values, we can compare whether they are the same by using an equivalence operator. The == operator returns true if two values have the same content and type. != (not equal) is true if they do not. For example:

x == 3.0        // Returns true if the local variable x's value is 3.0
x+1 != y        // Returns true if x is not exactly 1 greater than y
true != false   // Returns true

As with the arithmetic operators, the == and != operators are implemented as type-specific methods. Thus, each type can establish its own rules for equivalence. For example, two floating point numbers could be evaluated as equal if they are within some margin of error (resulting from floating point calculation rounding errors). Similarly, two lists might be equal if they have the exact same contents. A type must implement the == method to ensure its values can be compared.

Ordered Comparison

Comparison operators determine whether one value is greater or less than some other value. They work only on types that are comparable, such as numbers.

x >= 2          // Returns true if x is greater than or equal to 2 (>, <, <= are variants)
2 <= 2.0        // Returns false any time the types do not agree

Boolean Operators

Sometimes a conditional expression requires checking multiple conditions and then combining those results together into a single true/false determination. The boolean operators 'and', 'or' and 'not' ('!') are used to accomplish this. These operators are distinctly different than the bitwise logic operators ('&', '|', and '~') introduced in an earlier section.

For example:

0==3 or not 2<3 and 3==3   // Returns true ('and' is evaluated before 'or')

The logical operators work mostly how you would expect:

Expression usage

Conditional expressions need not only be found on control flow statements like if. They may also be incorporated as part of any arbitrary expression. For example:

imm isOne = (a == 1)    // isOne will be either true or false

_