How does purity apply to operators and their overrides?
← Purity Contracts · Ref: Q568
Operators follow the same purity rules as methods. If a parent defines a pure operator, the child override must also be pure (E05150). Many built-in operators are already pure.
PURE OPERATORS
Comparison operators (<=>), equality (==, <>), hash (#?), and string ($) are typically pure. They compute a result without modifying state.
OVERRIDE RULE
If a parent operator is pure, the child override must also be pure:
override operator <=> as pure -> other as MyType <- rtn as Integer: ...
OPERATOR ? IS SPECIAL
The operator ? (isSet check) is inherited from the base type. Custom classes use 'override operator ?' and it is typically pure:
override operator ? as pure <- rtn as Boolean: field?
MUTATING OPERATORS
Operators like +=, -=, :=:, :~:, :^: are mutating by nature and should NOT be pure. These modify the object in place.
See Q560 for pure method basics. See Q561 for purity in overrides. See Q245 for custom type operators. See Q241 for mutation operators.
Example
defines module qa.purity.operators defines class Temperature as open degrees <- 0.0 Temperature() -> degrees as Float this.degrees: degrees degrees() as pure <- rtn as Float: degrees //Pure comparison operator operator <=> as pure -> other as Temperature <- rtn as Integer: degrees <=> other.degrees //Pure equality derived from comparison default operator == //Pure string representation operator $ as pure <- rtn as String: $degrees + " degrees" //Pure hash code operator #? as pure <- rtn as Integer: #? degrees //Pure isSet check override operator ? as pure <- rtn as Boolean: degrees? //Child must keep operators pure Celsius extends Temperature Celsius() -> degrees as Float super(degrees) //Override of pure operator must be pure override operator $ as pure <- rtn as String: `${degrees()} C` default operator ? defines program PureOperatorsDemo() stdout <- Stdout() temp1 <- Temperature(20.0) temp2 <- Temperature(30.0) stdout.println(`${temp1} vs ${temp2}`) stdout.println(`Equal: ${temp1 == temp2}`) stdout.println(`Compare: ${temp1 <=> temp2}`) cel <- Celsius(100.0) stdout.println(`Celsius: ${cel}`)
Common mistakes
E07500 — The parent Temperature.operator $ is pure. The child Celsius override must also be pure. Removing purity from the operator override violates the contract. See ek9 -h E07500 for details.
Incorrect:
override operator $
Correct:
override operator $ as pure
E05120 — When overriding a parent operator, the override keyword is required. Omitting it on operator $ in Celsius triggers shadowing detection. See ek9 -h E05120 for details.
Incorrect:
operator $ as pure
Correct:
override operator $ as pure
Other ways to ask this
- Can operators be pure in EK9?
- Must I override a pure operator with a pure operator?
- How does purity interact with operator overriding?
Coming from another language?
Java: operator overloading not supported, no purity concept. Kotlin: operator overloading exists but no purity enforcement. Rust: trait-based operators, no purity markers. EK9: operators follow identical purity rules to methods, E05150 applies to operator overrides.
Keywords: open, equality, isSet, purity, override, operator, abstract, immutable, pure, contract, mutation, E05150, comparison, side-effect, virtual