Comparison Operators
| Operator | Description ( xoperatory) | x,ysame type or are numeric | x,ydifferent types | 
|---|---|---|---|
| == | xis equals toy | error if not defined | falseif not defined | 
| != | xis not equals toy | error if not defined | trueif not defined | 
| > | xis greater thany | error if not defined | falseif not defined | 
| >= | xis greater than or equals toy | error if not defined | falseif not defined | 
| < | xis less thany | error if not defined | falseif not defined | 
| <= | xis less than or equals toy | error if not defined | falseif not defined | 
Comparison operators between most values of the same type are built in for all standard types.
Floating-point numbers interoperate with integers
Comparing a floating-point number with an integer is also supported.
42 == 42.0;         // true
42.0 == 42;         // true
42.0 > 42;          // false
42 >= 42.0;         // true
42.0 < 42;          // falseDecimal numbers interoperate with integers
Comparing a decimal number with an integer is also supported.
let d = parse_decimal("42");
42 == d;            // true
d == 42;            // true
d > 42;             // false
42 >= d;            // true
d < 42;             // falseStrings interoperate with characters
Comparing a string with a character is also supported, with the character first turned into a string before performing the comparison.
'x' == "x";         // true
"" < 'a';           // true
'x' > "hello";      // falseComparing 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.
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 typeSafety 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 up and for subtle errors to creep in.
// 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 typesBoolean Operators
All boolean operators are built in for the bool data type.
| Operator | Description | Arity | Short-circuits? | 
|---|---|---|---|
| !(prefix) | NOT | unary | no | 
| && | AND | binary | yes | 
| & | AND | binary | no | 
| || | OR | binary | yes | 
| | | OR | binary | no | 
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.
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 evaluatedNull-Coalescing Operator
| Operator | Description | Arity | Short-circuits? | 
|---|---|---|---|
| ?? | Null-coalesce | binary | yes | 
The null-coalescing operator (??) returns the first operand if it is not (), or the second
operand if the first operand is ().
This operator short-circuits  – meaning that the second operand will not be evaluated if the
first operand is not ().
a ?? b              // returns 'a' if it is not (), otherwise 'b'
a() ?? b();         // b() is only evaluated if a() is ()Use the null-coalescing operator to implement default values for non-existent object map properties.
let map = #{ foo: 42 };
// Regular property access
let x = map.foo;            // x == 42
// Non-existent property
let x = map.bar;            // x == ()
// Default value for property
let x = map.bar ?? 42;      // x == 42Short-circuit loops and early returns
The following statements are allowed to follow the null-coalescing operator:
This means that you can use the null-coalescing operator to short-circuit loops and/or
early-return from functions when the value tested is ().
let total = 0;
for value in list {
    // Whenever 'calculate' returns '()', the loop stops
    total += calculate(value) ?? break;
}In Operator
The in operator is simply syntactic sugar for a call to the contains function.
Similarly, !in is a call to !contains.
The in operator is used to check for containment – i.e. whether a particular collection
data type contains a particular item.
Similarly, !in is used to check for non-existence – i.e. it is true if a particular
collection data type does not contain a particular item.
42 in array;
array.contains(42);     // <- the above is equivalent to this
123 !in array;
!array.contains(123);   // <- the above is equivalent to thisBuilt-in support for standard data types
| Data type | Check for | 
|---|---|
| Numeric range | integer number | 
| Array | contained item | 
| Object map | property name | 
| String | sub-string or character | 
Examples
let array = [1, "abc", 42, ()];
42 in array == true;                // check array for item
let map = #{
    foo: 42,
    bar: true,
    baz: "hello"
};
"foo" in map == true;               // check object map for property name
'w' in "hello, world!" == true;     // check string for character
'w' !in "hello, world!" == false;
"wor" in "hello, world" == true;    // check string for sub-string
42 in -100..100 == true;            // check range for number