# Logic Operators

## Comparison Operators

OperatorDescription
(`x` operator `y`)
`x`, `y` same type, or numeric`x`, `y` different types
`==``x` is equals to `y`error if not defined`false` if not defined
`!=``x` is not equals to `y`error if not defined`true` if not defined
`>``x` is greater than `y`error if not defined`false` if not defined
`>=``x` is greater than or equals to `y`error if not defined`false` if not defined
`<``x` is less than `y`error if not defined`false` if not defined
`<=``x` is less than or equals to `y`error if not defined`false` 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.