Select the earlier time from two shift starts, and which one wins when they are equal?
← Operators and Expressions · Ref: Q1218
The <? coalescing operator returns the lesser of two values, handling unset gracefully.
earlierStart() as pure -> left as Time right as Time <- rtn as Time: left <? right
If both times are set and different, <? returns the earlier one. If one is unset, it returns the set one. If both are unset, the result is unset.
When the two times are equal (<=> gives 0), <? returns the LEFT operand. For Time values equal means identical, so you cannot tell; it matters when <=> ties on objects that differ, such as a record whose <=> compares one field. To get the right operand on a tie, swap the operands: right <? left. There is no separate 'or equal' form - the inclusive operators were removed (E01095) because this is the one tie rule for <? and >?. See Q1227 for both operators side by side.
Do not confuse any coalescing operator with :=? (assign-if-unset). See Q1226 for the contrast.
Example
#!ek9 defines module qa.operators.coalescetie.time defines function earlierStart() as pure -> left as Time right as Time <- rtn as Time: left <? right defines program CoalesceTieTimeDemo() stdout <- Stdout() // === BOTH SHIFTS SCHEDULED — returns the earlier === morningShift <- 06:00 dayShift <- 09:00 firstStart <- earlierStart(morningShift, dayShift) stdout.println(`First shift starts: ${firstStart}`) // === EQUAL TIMES — returns the shared time (the left operand) === shiftA <- 08:00 shiftB <- 08:00 sameStart <- earlierStart(shiftA, shiftB) stdout.println(`Both start at: ${sameStart}`) // === ONE SHIFT UNSCHEDULED — returns the scheduled one === scheduledShift <- 07:30 unscheduledShift <- Time() onlyShift <- earlierStart(scheduledShift, unscheduledShift) stdout.println(`Scheduled shift: ${onlyShift}`) // === BOTH UNSCHEDULED — result is unset === missingShift <- Time() noShiftB <- Time() bothMissing <- earlierStart(missingShift, noShiftB) if bothMissing? stdout.println(`Shift: ${bothMissing}`) else stdout.println("No shifts scheduled")
Common mistakes
E50030 — '<=' is a comparison that yields Boolean, so assigning 'left <= right' to a Time return is a type mismatch; use the coalescing '<?' which returns the lesser Time (the left one on a tie) and handles unset values. See ek9 -h E50030 for details.
Incorrect:
<- rtn as Time: left <= right
Correct:
<- rtn as Time: left <? right
Other ways to ask this
- How do I find the lesser of two Time values when one shift might be unscheduled?
- Two shifts have start times but one could be empty — pick the earlier time.
- In Java I'd need null checks before comparing with isBefore or equals. What does EK9 use?
- Migrating from Python where I use min() for times — what does EK9's null-safe minimum return when the two are equal?
Coming from another language?
Java: a == null ? b : b == null ? a : !a.isAfter(b) ? a : b. Python: min(a, b) returns the first of equal values, as <? does. Kotlin: listOfNotNull(a, b).minOrNull(). EK9: left <? right — one operator handles all cases including equality, and the left operand wins a tie.
Keywords: <?, coalescing, earlier, equal, minimum, schedule, shift, tie, time