Select the higher-priority Task from two optional task records.

← Operators and Expressions · Ref: Q1229

Define a custom <=> operator that compares only the priority field. Lower priority number means higher priority, so use <? to pick the more urgent task.

  higherPriority() as pure
    -> left as Task, right as Task
    <- rtn as Task: left <? right

The custom <=> lets you control which field determines ordering. The <? coalescing operator uses <=> to find the lesser value — and since lower priority number means higher urgency, <? picks the more urgent task.

See Q1228 for <? with default operator. See Q1049 for custom comparison operators.

Example

defines module qa.operators.coalescemax.record

  defines record

    Task
      title as String: String()
      priority as Integer: 0

      Task()
        ->
          title as String
          priority as Integer
        this.title: title
        this.priority: priority

      operator <=> as pure
        -> other as Task
        <- rtn as Integer: priority <=> other.priority

      default operator

  defines function

    higherPriority() as pure
      ->
        left as Task
        right as Task
      <- rtn as Task: left <? right

  defines program

    CoalesceMaxRecordDemo()
      stdout <- Stdout()

      // === BOTH SET — <? returns the lesser priority number (higher urgency) ===

      criticalTask <- Task("Fix outage", 1)
      normalTask <- Task("Update docs", 5)
      moreUrgent <- higherPriority(criticalTask, normalTask)
      stdout.println(`More urgent: ${moreUrgent}`)

      // === ONE UNSET — returns the set one ===

      knownTask <- Task("Deploy release", 3)
      unknownTask <- Task()
      available <- higherPriority(knownTask, unknownTask)
      stdout.println(`Available task: ${available}`)

      // === BOTH UNSET — result is unset ===

      pendingA <- Task()
      pendingB <- Task()
      noTask <- higherPriority(pendingA, pendingB)
      if noTask?
        stdout.println(`Task: ${noTask}`)
      else
        stdout.println("No task available")

      // === USE >? FOR LOWEST PRIORITY (largest number) ===

      lowest <- criticalTask >? normalTask
      stdout.println(`Lowest priority: ${lowest}`)

Common mistakes

E07550 — The <=> operator must return Integer, not Boolean. It returns negative, zero, or positive to indicate ordering. See ek9 -h E07550 for details.

Incorrect:

      operator <=> as pure
        -> other as Task
        <- rtn as Boolean: priority < other.priority

Correct:

      operator <=> as pure
        -> other as Task
        <- rtn as Integer: priority <=> other.priority
Other ways to ask this
  • How do I pick the task with the higher priority using coalescing operators?
  • Given two optional Task records with priority numbers, choose the more urgent one.
  • In Java I'd use Comparator.comparing(Task::getPriority) to find min priority. What does EK9 use?
  • Migrating from Python where I use min(tasks, key=lambda t: t.priority) — what is the EK9 equivalent?

Coming from another language?

Java: Collections.min(tasks, Comparator.comparingInt(Task::getPriority)). Python: min(tasks, key=lambda t: t.priority). Kotlin: tasks.minByOrNull { it.priority }. EK9: left <? right with custom <=> on priority field.

Keywords: priority, custom operator, task, coalescing, <?, record, minimum, comparison