Boolean

A boolean value is either true or false. Booleans appear naturally wherever you make a decision: in if conditions, loop filters, and comparisons. Loft adds a third state called null — meaning "no value" — which behaves like false whenever a boolean is expected.

This design means you rarely need to write a separate null-check: !x is true both when x is false and when x is null.

fn main() {

A comparison produces a boolean result directly. ! flips a boolean: true → false, false → true.

  assert(!(3 > 2 + 4), "3 is not greater than 6");
  assert(true as text == "true", "Convert boolean to text");

Logical operators: and / or

and (also &&) is true only when both sides are true. or (also ||) is true when at least one side is true. Both skip the right side when the left side already determines the result. For example, false and X is always false, so X is never evaluated. This matters when the right side could produce null or has a side effect.

  assert(1 > 0 and 2 > 1, "Both conditions true");
  assert(1 > 2 or 3 > 2, "Second condition true");
  assert(!(1 > 2 && 3 > 2), "First false → whole 'and' is false");
  assert(!(1 > 2 || 3 > 4), "Both false → 'or' is false");

Null in boolean context

Division by zero (and other failed operations) produce null. Null in a boolean context is treated as false, so ! is true. This lets you write guard clauses without a separate null-check syntax: if !result { ... handle missing value ... }

  zero = 0;
  assert(!(12 / zero), "null from division-by-zero is false-like");
  assert(12 > 0, "positive integer is true");

Bitwise operators

While and/or work on true/false values, bitwise operators work on the individual bits of an integer. They are useful for flags, masks, and low-level data manipulation.

'&'  — keeps only bits set in BOTH operands (AND)
'|'  — keeps bits set in EITHER operand (OR)
'<<' — shift bits left N positions  (×2^N)
'>>' — shift bits right N positions (÷2^N)

Tip: & binds less tightly than comparison operators. Use parentheses when you mix bitwise and comparison expressions in the same condition.

  assert((0x0f & 0xa8) == 8, "Bitwise AND: keeps only bits in both");
  assert((0xf0 | 0x0f) == 0xff, "Bitwise OR: combines bits from either");
  assert(1 << 4 == 16, "Left shift: 1 × 2^4 = 16");
  assert(256 >> 3 == 32, "Right shift: 256 ÷ 2^3 = 32");

Negation

! is the logical NOT operator. It flips any boolean expression.

  assert(!false, "not false is true");
  assert(!(1 > 2), "not false comparison is true");

Formatting booleans

Booleans can be embedded in a format string like any other value. The ^ alignment specifier centres the value in a field of given width. < aligns left, > aligns right (right-alignment is the default).

  assert("1{true:^7}2" == "1 true  2", "Centred boolean in field of width 7");
  assert("{false}" == "false", "Plain boolean format");

& vs and

& is bitwise AND on integers; and (or &&) is logical AND on booleans. Writing a & b where both sides are booleans is a compile error — the compiler requires and or && for boolean logic.

  flag_a = 3 > 1;

true

  flag_b = 4 > 2;

true

  assert(flag_a and flag_b, "Correct: logical AND on two booleans");
}