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

← Operators and Expressions · Ref: Q1321

A type's logical-NOT (and bitwise complement) operator is DECLARED with the '~' symbol. When you declare 'operator not' on a class, record, or trait the compiler raises E07650 (BAD_NOT_OPERATOR) and tells you to use '~'.

Define the operator with '~'; on a custom type it must be pure, take no arguments, and return the SAME type (so 'Switch' returns a negated 'Switch'):

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

At a CALL SITE both forms negate: '~value' and 'not value' are the same operator, on the built-in Boolean and on any type that declares '~' (so 'not on' calls Switch's '~'). Only the C-style '!value' does not exist in EK9. ('not' also prefixes the membership tests 'not contains' / 'not in'.)

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 Switch (the same type).
    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}`)

      //At a call site 'not' is the word form of the same '~' operator
      alsoOff <- not on
      stdout.println(`Not on:    ${alsoOff}`)

      enabled <- true
      stdout.println(`not enabled: ${not enabled}`)

Common mistakes

E07650 — Declaring 'operator not' on a type raises E07650. Declare the operator as '~', which is EK9's logical-NOT and bitwise-complement operator; callers may then write either '~value' or 'not 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: a type declares negation as 'operator ~' ('operator not' is E07650); at call sites 'not x' and '~x' both negate, and '!' does not exist.

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