How do I implement comparison operators on a record for sorting?
← Operators and Expressions · Ref: Q1049
Implement the <=> (spaceship) operator on your record. Then derive <, >, <=, >= from it. All comparison operators must be pure.
defines record Priority level as Integer: 0
operator <=> as pure -> other as Priority <- rtn as Integer: level <=> other.level
operator < as pure -> other as Priority <- rtn as Boolean: (this <=> other) < 0
operator > as pure -> other as Priority <- rtn as Boolean: (this <=> other) > 0
operator <= as pure -> other as Priority <- rtn as Boolean: (this <=> other) <= 0
operator >= as pure -> other as Priority <- rtn as Boolean: (this <=> other) >= 0
Once these are defined, you can sort lists and use coalescing operators:
smaller <- priorityA <? priorityB larger <- priorityA >? priorityB
The coalescing operators <? and >? return the lesser or greater value. They work because the comparison operators are defined.
See Q1050 for coalescing operators on a class. See Q239 for comparison ordering. See Q1051 for operators on traits.
Example
defines module qa.operators.comparisonrecord defines record Priority level as Integer: 0 label as String: String() Priority() -> level as Integer label as String this.level :=: level this.label :=: label operator <=> as pure -> other as Priority <- rtn as Integer: level <=> other.level operator < as pure -> other as Priority <- rtn as Boolean: (this <=> other) < 0 operator > as pure -> other as Priority <- rtn as Boolean: (this <=> other) > 0 operator <= as pure -> other as Priority <- rtn as Boolean: (this <=> other) <= 0 operator >= as pure -> other as Priority <- rtn as Boolean: (this <=> other) >= 0 default operator defines program ComparisonRecordDemo() stdout <- Stdout() high <- Priority(10, "Critical") medium <- Priority(5, "Normal") low <- Priority(1, "Low") stdout.println(`High > Low: ${high > low}`) stdout.println(`Medium <= High: ${medium <= high}`) //Coalescing: get the lesser/greater lesser <- high <? medium greater <- low >? medium stdout.println(`Lesser: ${lesser}`) stdout.println(`Greater: ${greater}`)
Common mistakes
E07520 — The < operator must return Boolean, not Integer. Use <=> for Integer comparison results, < for Boolean.
Incorrect:
operator < as pure -> other as Priority <- rtn as Integer: level - other.level
Correct:
operator < as pure -> other as Priority <- rtn as Boolean: (this <=> other) < 0
Other ways to ask this
- How do <, >, <=, >= work on a record?
- Show me comparison operators on a custom record
- How do I make a record sortable in EK9?
Coming from another language?
Java: implements Comparable. Python: __lt__, __gt__, etc. Rust: derive Ord. EK9: define <=> then derive <, >, <=, >= from it.
Keywords: record, sort, operator, comparison, spaceship