How do boolean and bitwise operators work in EK9?

← Operators and Expressions · Ref: Q244

EK9 uses the SAME operator names for both Boolean logic and Bits manipulation. The compiler resolves which implementation to use based on the operand types.

SHARED OPERATORS

The 'and', 'or', 'xor' operators work on BOTH Boolean and Bits types. All are pure, take 1 argument, and return a value.

For Boolean:

  result <- true and false
  result <- true or false
  result <- true xor true

For Bits:

  mask <- 0b1100 and 0b1010
  combined <- 0b1100 or 0b1010
  toggled <- 0b1100 xor 0b1010

NEGATION (~)

The ~ operator works on Boolean (logical NOT) and Bits (bitwise NOT). Numbers use unary - for negation, not ~.

  notTrue <- ~ true
  flipped <- ~ 0b1100

BIT SHIFT OPERATORS (<< and >>)
The << and >> operators are Bits-only. They shift bits left or right. Both are pure, take 1 Integer argument, and return a new Bits value.

  shifted <- 0b0001 << 3
  result <- 0b1000 >> 2

Bits values grow as needed with left shift. Right shift discards bits.

BITS ARE NOT INTEGERS

Bits are ordered collections of individual bits. They are NOT integers. You cannot add Bits or use them in arithmetic. They support: and, or, xor, ~ (NOT), << (shift left), >> (shift right), length, ==, <>, $.

BITS LITERALS

Bits literals use the 0b prefix:

  flags <- 0b010011
  mask <- 0b111100

See Q30 for Boolean basics. See Q40 for Bits type. See Q238 for the complete operator set. See Q240 for arithmetic operators.

Example

defines module qa.operators.booleanbitwise

  defines program

    BooleanBitwiseDemo()
      stdout <- Stdout()

      // === BOOLEAN LOGIC ===

      a <- true
      b <- false

      stdout.println(`and: ${a and b}`)
      stdout.println(`or: ${a or b}`)
      stdout.println(`xor: ${a xor b}`)
      stdout.println(`not: ${~ a}`)

      // === BITWISE OPERATIONS (same syntax!) ===

      mask1 <- 0b1100
      mask2 <- 0b1010

      stdout.println(`Bits and: ${mask1 and mask2}`)
      stdout.println(`Bits or: ${mask1 or mask2}`)
      stdout.println(`Bits xor: ${mask1 xor mask2}`)
      stdout.println(`Bits not: ${~ mask1}`)

      // === BIT SHIFT ===

      oneBit <- 0b0001
      shifted <- oneBit << 3
      stdout.println(`Shift left: ${shifted}`)

      wide <- 0b1000
      narrow <- wide >> 2
      stdout.println(`Shift right: ${narrow}`)

      // === BITS ARE NOT INTEGERS ===

      flags <- 0b010011
      stdout.println(`Flags length: ${length flags}`)
      stdout.println(`Flags equal: ${flags == 0b010011}`)

Common mistakes

E07620 — Boolean negation in EK9 uses the ~ operator, not ! which is the factorial operator for Integer. The ! operator is not defined on Boolean. See ek9 -h E07620 for details.

Incorrect:

stdout.println(`not: ${a!}`)

Correct:

stdout.println(`not: ${~ a}`)
Other ways to ask this
  • What is the difference between boolean and bitwise operators in EK9?
  • How do shift operators work on Bits in EK9?
  • Does EK9 use the same syntax for boolean and bitwise operations?

Coming from another language?

Java: && || for boolean, & | ^ for bitwise, different syntax for same concepts. Python: and or not for boolean, & | ^ ~ for bitwise, different syntax. Rust: && || for boolean, & | ^ for bitwise, ! for both not. Go: && || for boolean, & | ^ for bitwise, different syntax. Kotlin: && || for boolean, and or xor for bitwise on Int. JavaScript: && || for boolean, & | ^ for bitwise, different syntax. EK9: 'and' 'or' 'xor' '~' for BOTH Boolean and Bits (same syntax, type-based dispatch), << >> for Bits only.

Keywords: expression, left, operator, xor, mask, bitwise, bits, logic, flag, binary, and, boolean, not, right, shift, or, negate