Logic Operators

Comparison Operators

OperatorDescription
(x operator y)
x, y same type, or numericx, y different types
==x is equals to yerror if not definedfalse if not defined
!=x is not equals to yerror if not definedtrue if not defined
>x is greater than yerror if not definedfalse if not defined
>=x is greater than or equals to yerror if not definedfalse if not defined
<x is less than yerror if not definedfalse if not defined
<=x is less than or equals to yerror if not definedfalse if not defined

Comparison between most values of the same type are built in for all standard types.

Floating-point numbers can inter-operate with integers

Comparing a floating-point number (FLOAT or Decimal) with an integer is also supported.


#![allow(unused)]
fn main() {
42 == 42.0;         // true

42.0 == 42;         // true

42.0 > 42;          // false

42 >= 42.0;         // true

42.0 < 42;          // false
}

Strings can inter-operate with characters

Comparing a string with a character is also supported, with the character first turned into a string before performing the comparison.


#![allow(unused)]
fn main() {
'x' == "x";         // true

"" < 'a';           // true

'x' > "hello";      // false
}

Comparing different types defaults to false

Comparing two values of different data types defaults to false unless the appropriate operator functions have been registered.

The exception is != (not equals) which defaults to true. This is in line with intuition.


#![allow(unused)]
fn main() {
42 > "42";          // false: i64 cannot be compared with string

42 <= "42";         // false: i64 cannot be compared with string

let ts = new_ts();  // custom type

ts == 42;           // false: different types cannot be compared

ts != 42;           // true: different types cannot be compared

ts == ts;           // error: '==' not defined for the custom type
}

Safety valve: Comparing different numeric types has no default

Beware that the above default does NOT apply to numeric values of different types (e.g. comparison between i64 and u16, i32 and f64) – when multiple numeric types are used it is too easy to mess and for subtle errors to creep in.


#![allow(unused)]
fn main() {
// Assume variable 'x' = 42_u16, 'y' = 42_u16 (both types of u16)

x == y;             // true: '==' operator for u16 is built-in

x == "hello";       // false: different non-numeric operand types default to false

x == 42;            // error: ==(u16, i64) not defined, no default for numeric types

42 == y;            // error: ==(i64, u16) not defined, no default for numeric types
}

Caution: Beware operators for custom types

Operators are completely separate from each other. For example:

  • != does not equal !(==)

  • > does not equal !(<=)

  • <= does not equal < plus ==

  • <= does not imply <

Therefore, if a custom type misses an operator definition, it simply raises an error or returns the default.

This behavior can be counter-intuitive.


#![allow(unused)]
fn main() {
let ts = new_ts();  // custom type with '<=' and '==' defined

ts <= ts;           // true: '<=' defined

ts < ts;            // error: '<' not defined, even though '<=' is

ts == ts;           // true: '==' defined

ts != ts;           // error: '!=' not defined, even though '==' is
}

It is strongly recommended that, when defining operators for custom types, always define the full set of six operators (or at least the == and != pair) together.

Boolean operators

OperatorDescriptionArityShort-Circuits?
! (prefix)boolean NOTunaryno
&&boolean ANDbinaryyes
&boolean ANDbinaryno
||boolean ORbinaryyes
|boolean ORbinaryno

Double boolean operators && and || short-circuit – meaning that the second operand will not be evaluated if the first one already proves the condition wrong.

Single boolean operators & and | always evaluate both operands.


#![allow(unused)]
fn main() {
a() || b();         // b() is not evaluated if a() is true

a() && b();         // b() is not evaluated if a() is false

a() | b();          // both a() and b() are evaluated

a() & b();          // both a() and b() are evaluated
}

All boolean operators are built in for the bool data type.