Comparison

A comparison tests two values and produces a bool.

OperatorTestLevel
<less than11
<=less than or equal11
>greater than11
>=greater than or equal11
==equal10
!=not equal10
let a = 10;
let b = 20;
PrintLine("{} {} {} {}", a == b, a != b, a < b, a >= b);

This prints false true true false. The ordering operators bind more tightly than == and !=, and all of them bind more tightly than && and ||, so offset + length <= capacity && capacity != 0 needs no parentheses.

Operand types

Numbers compare under the same operand rules as arithmetic: one type, a literal that takes the other operand's type, or two integers of one signedness, where the narrower widens. A signed and an unsigned integer have no common type:

error: operator '<' cannot compare left operand 'uint64' with right operand 'int64'
  note: the operands differ in signedness, so neither converts to the other's type
  help: convert one operand with 'as' to the type the operation should use

A literal must fit the other operand's type, so a test that could never be true is caught: with count: uint64, count == -1 is error: integer literal is out of range for type 'uint64'.

What can be compared

Type== !=< <= > >=
integers, floating-point numbersyesyes
charactersyesyes, by code
boolyesyes, false before true
enumsyesyes, by the members' values
pointersyes, and with nullyes, by address
structuresyes, field by field, when every field supports ==only through declared operators
tuplesyes, element by elementno
fixed-size arraysyes, element by elementno
variantsyes, case and payloadno
optionals, fallibles and sumsyes, between values of one typeno
slices, including string literalsnono

A structure, tuple or variant compares structurally only when every part can be compared. A structure gets ordering only from the operators it declares: != is derived from a declared ==, > from <, and <= and >= from < and == together — see Operator interfaces. Without them:

error: operator '<' is not defined for 'Point'
  note: a struct is compared through the operators it declares, never by its representation
  help: declare '<' on 'Point'

An optional compares with none and with a present value directly: found == none, found == 5. See Optionals.

Arrays and array literals.
rux 0.4.0 does not yet compare a fixed-size array with an array literal correctly: values == [1, 2] is false even when the elements are equal. Bind the literal to a name first.

Slices

A slice is a view of elements stored elsewhere. Comparing two views would compare the addresses they hold rather than the elements, so Rux refuses it — and a string literal is a char8[..] slice:

let same = name == "Rux";
error: operator '==' is not defined for slice type 'char8[..]'
  note: a slice is a view, so comparing the views would compare addresses rather than elements

Compare the elements one at a time, or use a type that declares ==, such as the Text package's String.

Floating-point comparisons

Floating-point comparisons follow IEEE 754. NaN is unordered: it is not equal to anything, itself included, and every ordering test with it is false:

let n = float64::NaN;
PrintLine("{} {} {}", n == n, n != n, n < 1.0);

This prints false true false. See Floating-point types for testing for NaN and for comparing computed values with a tolerance.

Comparisons do not chain

a < b < c is not a range test. It groups as (a < b) < c, which compares a bool with a number:

let inside = 1 < 2 < 3;
error: operator '<' cannot compare left operand 'bool8' with right operand 'int'

Combine two comparisons with &&: low <= value && value <= high.

See also