Find the nearest Waypoint from two optional locations using <? on a class with distance.
← Operators and Expressions · Ref: Q1231
Define a class with private fields, accessor methods, a custom <=> operator comparing distance, and 'default operator' last. Then use <? in a pure function.
nearerWaypoint() as pure -> left as Waypoint, right as Waypoint <- rtn as Waypoint: left <? right
Classes are used instead of records when you need behaviour (methods). Waypoint has name() and distance() accessor methods because class fields are always private. The <? operator works identically on classes and records — it only requires <=> to be defined.
See Q1228 for <? on records.
Example
defines module qa.operators.coalesce.classmethod defines class Waypoint waypointName <- String() waypointDistance <- Float() Waypoint() -> name as String distance as Float waypointName :=: name waypointDistance :=: distance name() as pure <- rtn as String: waypointName distance() as pure <- rtn as Float: waypointDistance operator <=> as pure -> other as Waypoint <- rtn as Integer: waypointDistance <=> other.waypointDistance default operator defines function nearerWaypoint() as pure -> left as Waypoint right as Waypoint <- rtn as Waypoint: left <? right defines program CoalesceClassMethodDemo() stdout <- Stdout() // === BOTH SET — compares by distance === basecamp <- Waypoint("Basecamp", 2.5) summit <- Waypoint("Summit", 8.7) nearer <- nearerWaypoint(basecamp, summit) stdout.println(`Nearer waypoint: ${nearer}`) // === ONE UNSET — returns the set one === knownPoint <- Waypoint("Checkpoint", 5.0) unknownPoint <- Waypoint() available <- nearerWaypoint(knownPoint, unknownPoint) stdout.println(`Available waypoint: ${available}`) // === BOTH UNSET — result is unset === lostA <- Waypoint() lostB <- Waypoint() noWaypoint <- nearerWaypoint(lostA, lostB) if noWaypoint? stdout.println(`Waypoint: ${noWaypoint}`) else stdout.println("No waypoint available") // === >? FOR FARTHEST === farthest <- basecamp >? summit stdout.println(`Farthest waypoint: ${farthest}`)
Common mistakes
E07290 — Class fields are always private. To expose state, define accessor methods. Public fields are only allowed on records. See ek9 -h E07290 for details.
Incorrect:
name as String: String()
Correct:
name() as pure <- rtn as String: waypointName
Other ways to ask this
- How do I use <? coalescing on a class instead of a record?
- Given two optional Waypoint objects with distance fields, pick the nearer one.
- In Java I'd implement Comparable on a class to use min(). What does EK9 use?
- Migrating from Python where I use min(wp1, wp2, key=lambda w: w.distance) — what is the EK9 pattern?
Coming from another language?
Java: class Waypoint implements Comparable<Waypoint> with compareTo(). Python: class with __lt__ and min(). Kotlin: class with compareTo(). EK9: class with <=> operator, then left <? right.
Keywords: accessor, distance, coalescing, <?, method, waypoint, minimum, class