Why can't I provide a signature or body when using 'default operator' in EK9?

← Classes and OOP · Ref: Q835

The 'default' keyword on an operator means 'compiler, auto-generate this operator from the existing fields and prerequisite operators'. Adding a signature, modifiers like 'as pure', parameters, or a body contradicts this — you are simultaneously asking the compiler to generate it AND manually specifying it.

THE RULE

- 'default operator <=>' — valid, compiler generates comparator
- 'default operator' — valid, compiler generates ALL supported operators
- 'default operator >= as pure' — ERROR E07230, contradictory
- 'default operator ? as pure <- rtn as Boolean: x?' — ERROR E07230, contradictory

WHY IT IS AN ERROR

If you want auto-generation, write 'default operator <name>' with nothing else. If you want a custom implementation, write the full operator without 'default'. Mixing the two indicates a misunderstanding of what 'default' means.

PREREQUISITE OPERATORS

Some default operators require other operators to exist first. For example, 'default operator >=' needs the comparator '<=>'. You can provide '<=>'' explicitly and default the rest.

THIS EXAMPLE

The Shape record provides an explicit comparator, then uses 'default operator' to auto-generate all remaining supported operators (>=, <=, >, <, ==, <>, $, #?).

See Q116 for default operator overview. See Q96 for operator semantics. See Q774 for abstract constructor.

Example

defines module qa.classesandoop.default.operator.signature

  defines record

    Shape
      name <- String()
      sides <- 0

      Shape()
        ->
          n as String
          s as Integer
        name :=: n
        sides :=: s

      //Explicit comparator — prerequisite for defaulting >=, <=, etc.
      operator <=> as pure
        -> arg0 as Shape
        <- rtn as Integer: sides <=> arg0.sides

      //Auto-generate ALL remaining supported operators
      default operator

  defines class

    Config
      label <- "default"
      priority <- 0

      default Config()

      Config()
        ->
          l as String
          p as Integer
        label :=: l
        priority :=: p

      describe()
        <- rtn as String: `${label} (priority ${priority})`

      //Explicit comparator
      operator <=> as pure
        -> arg0 as Config
        <- rtn as Integer: priority <=> arg0.priority

      //Selective default — just the isSet operator
      default operator ?

  defines program

    DefaultOperatorDemo()
      stdout <- Stdout()

      triangle <- Shape("triangle", 3)
      square <- Shape("square", 4)

      if triangle?
        stdout.println(`Triangle >= Square: ${triangle >= square}`)
        stdout.println(`Triangle == Square: ${triangle == square}`)
        stdout.println("Triangle $: " + $triangle)

      c1 <- Config("high", 10)
      c2 <- Config("low", 1)
      if c1?
        stdout.println(c1.describe())
        stdout.println(`c1 > c2: ${c1 <=> c2 > 0}`)

Common mistakes

E07230 — Cannot provide a signature or body with 'default operator'. The keyword 'default' means the compiler generates it. Either remove 'default' and write the operator manually, or remove the signature/body. See ek9 -h E07230 for details.

Incorrect:

      //Auto-generate ALL remaining supported operators
      default operator >= as pure
        -> arg0 as Shape
        <- rtn as Boolean: false

Correct:

      //Auto-generate ALL remaining supported operators
      default operator

E07230 — Providing 'as pure' modifier and a body with 'default' is contradictory. Use 'default operator ?' alone for auto-generation, or remove 'default' and write the full operator. See ek9 -h E07230 for details.

Incorrect:

      default operator ? as pure
        <- rtn as Boolean: name?

Correct:

      default operator ?
Other ways to ask this
  • What is E07230 DEFAULT_WITH_OPERATOR_SIGNATURE?
  • Why does 'default operator >= as pure' fail to compile?
  • What does 'default' mean on an operator and why can't I add parameters?

Coming from another language?

Java: no operator overloading or auto-generation. Kotlin: data class generates all-or-nothing. Rust: #[derive(PartialEq, Hash)] is selective auto-generation. EK9: 'default operator' is selective, but 'default' and manual specification are mutually exclusive — prevents contradictory declarations.

Keywords: auto-generate, contradictory, default, pure, operator, modifier, prerequisite, signature, E07230, body