Why can't I declare 'operator !=' on my EK9 type?

← Operators and Expressions · Ref: Q1320

EK9's not-equal operator is '<>' (mathematical notation), not the C-family '!='. When you declare an operator on a type you must name it '<>'. Declaring 'operator != as pure' triggers E07640 (BAD_NOT_EQUAL_OPERATOR) because '!=' is not a valid EK9 operator symbol for a declaration.

Replace 'operator !=' with 'operator <>'. The operator must be pure, take exactly one argument, and return Boolean.

For comparison with the type ITSELF you write neither: the type declares its sameness once - '<=>' for an ordered type, or '==' for an equatable-only type - with a matching '#?', and the compiler generates '<>' (and ==, <, <=, >, >= from '<=>'). Hand-writing a self '<>' is E07181. You declare 'operator <>' by hand only against an unrelated type, as Score does with Integer here. EK9 chose '<>' because it is the mathematical not-equal form (the same as Pascal, SQL and BASIC) and composes naturally with '<' and '>'.

See Q238 for the complete fixed operator set. See Q239 for comparison and ordering operators.

Example

defines module qa.operators.notequal

  defines class

    Score
      points <- Integer()

      Score() as pure
        -> points as Integer
        this.points :=: points

      //The sameness: ==, <>, <, <=, >, >= with another Score are generated from it,
      //so '<>' for Score is never written by hand
      operator <=> as pure
        -> other as Score
        <- rtn as Integer: points <=> other.points

      operator #? as pure
        <- rtn as Integer: #?points

      //THE FIX: EK9's not-equal operator is '<>', NOT '!='.
      //Declaring 'operator !=' would trigger E07640.
      //(Here '<>' compares with an unrelated type, Integer, so it is written by hand.)
      operator <> as pure
        -> threshold as Integer
        <- rtn as Boolean: points <> threshold

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

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

  defines program

    NotEqualOperatorDemo()
      stdout <- Stdout()

      a <- Score(10)
      b <- Score(20)

      stdout.println(`Equal: ${a == b}`)
      stdout.println(`Not equal: ${a <> b}`)

Common mistakes

E07640 — EK9 uses the mathematical not-equal symbol '<>', not the C-family '!='. Declaring 'operator !=' is not a valid EK9 operator name and triggers E07640. Rename the declaration to 'operator <>' (pure, one argument, returns Boolean). For comparison with the type itself, write neither: declare the sameness ('<=>' or '==') and '<>' is generated. See ek9 -h E07640 for details.

Incorrect:

operator != as pure
        -> threshold as Integer
        <- rtn as Boolean: points <> threshold

Correct:

operator <> as pure
        -> threshold as Integer
        <- rtn as Boolean: points <> threshold

E07181 — '<>' with the type itself is generated from its sameness (here '<=>'), so declaring it by hand for Score is E07181 (COMPARISON_GENERATED_FROM_SAMENESS). Delete it - 'a <> b' already works. See ek9 -h E07181 for details.

Incorrect:

      operator #? as pure
        <- rtn as Integer: #?points

      operator <> as pure
        -> other as Score
        <- rtn as Boolean: points <> other.points

Correct:

      operator #? as pure
        <- rtn as Integer: #?points
Other ways to ask this
  • What triggers E07640 BAD_NOT_EQUAL_OPERATOR?
  • How do I implement not-equal on a custom EK9 class?
  • Why does EK9 reject '!=' as an operator name?

Coming from another language?

Java/C++/Python/Rust/JavaScript: not-equal is '!=' and (where overloading exists) you implement it under that symbol or as a negated equals. EK9: the only not-equal operator symbol is '<>', and the compiler rejects a '!=' declaration at compile time (E07640, phase EXPLICIT_TYPE_SYMBOL_DEFINITION) rather than silently accepting an alternate spelling.

Keywords: comparison, <>, !=, operator, sameness, E07181, inequality, E07640, neq, not, equal, declaration