Why can't I declare 'operator not' on a type in EK9?

← Operators and Expressions · Ref: Q1321

EK9 has no 'not' operator and no '!' logical-NOT. The single logical-NOT (and bitwise complement) operator is '~'. When you declare 'operator not' on a class, record, or trait the compiler raises E07650 (BAD_NOT_OPERATOR) and tells you to use '~'. The same applies at call sites: write '~value', never '!value' or 'not value' for negation. ('not' IS a valid keyword, but only as the prefix of 'not contains' / 'not in' membership tests, not as a standalone logical-NOT.)

Define the operator with the '~' symbol; on a custom type it must be pure, take no arguments, and return the SAME type (so 'Switch' returns a negated 'Switch'). On the built-in Boolean, '~' yields the negated Boolean directly.

See Q244 for boolean and bitwise operators. See Q903 for operators that do NOT exist in EK9.

Example

defines module qa.operators.notistilde

  defines class

    //THE FIX: the logical-NOT operator is declared with '~', not 'not' and not '!'.
    //It is pure, takes no arguments, and returns a Boolean here.
    Switch
      active as Boolean: Boolean()

      Switch() as pure
        -> initial as Boolean
        active :=? initial

      operator ~ as pure
        <- rtn as Switch: Switch(~ active)

      operator $ as pure
        <- rtn as String: $ active

      override operator ? as pure
        <- rtn as Boolean: active?

  defines program

    NotOperatorDemo()
      stdout <- Stdout()

      on <- Switch(true)
      off <- ~ on

      stdout.println(`Switch on: ${on}`)
      stdout.println(`Negated:   ${off}`)

Common mistakes

E07650 — EK9 has no 'not' operator and no '!' logical-NOT; declaring 'operator not' on a type raises E07650. Rename the operator to '~', which is EK9's single logical-NOT and bitwise-complement operator. At call sites use '~value' too, never '!value'. See ek9 -h E07650 for details.

Incorrect:

operator not as pure
  <- rtn as Switch: Switch(~ active)

Correct:

operator ~ as pure
        <- rtn as Switch: Switch(~ active)
Other ways to ask this
  • What triggers E07650 when defining a logical NOT operator?
  • How do I implement boolean negation on a custom type in EK9?
  • Why does EK9 reject 'operator not' and want '~' instead?

Coming from another language?

Java/C/C++/JavaScript/Rust: '!' is logical NOT. Python: 'not' keyword is logical NOT. Kotlin: '!' plus an overloadable 'not()' operator function. EK9: neither '!' nor 'not' is a logical-NOT operator; '~' is the single negation operator, enforced at compile time both when DEFINING the operator (E07650) and at call sites.

Keywords: complement, E07650, negation, operator, not, logical, tilde, boolean