Demonstrate the difference between <? coalescing and :=? guarded assignment.
← Operators and Expressions · Ref: Q1226
<? and :=? are DIFFERENT operations despite the similar ? suffix.
<? is a COMPARISON — it returns the lesser of two values:
cheaperOf() as pure -> left as Money, right as Money <- rtn as Money: left <? right //Returns the smaller Money value, handles unset
:=? is an ASSIGNMENT — it sets a variable only if unset:
price <- Money() price :=? 9.99#USD //Assigns 9.99 USD because price was unset
KEY DIFFERENCES:
- <? compares two values and produces a result. It goes inside pure functions.
- :=? modifies a variable in place. It is an assignment, not a comparison.
- <? has a companion >? (coalescing maximum). :=? has no companion.
- <? always evaluates both sides. :=? skips the right side if the target is already set.
See Q1092 for <? and >? coalescing. See Q1038 for :=? fallback chains. See Q1227 for all four coalescing operators.
Example
defines module qa.operators.coalescevsguard defines function // <? is a COMPARISON — used inside pure functions cheaperOf() as pure -> left as Money right as Money <- rtn as Money: left <? right earlierOf() as pure -> left as Date right as Date <- rtn as Date: left <? right defines program CoalesceVsGuardDemo() stdout <- Stdout() // ============================================================ // PART 1: <? COALESCING MINIMUM — compares two values // ============================================================ // <? returns the LESSER of two values vendorA <- 149.99#USD vendorB <- 129.50#USD bestPrice <- cheaperOf(vendorA, vendorB) stdout.println(`Cheaper quote (both set): ${bestPrice}`) // <? with one unset — returns the set value knownQuote <- 199.00#USD missingQuote <- Money() availableQuote <- cheaperOf(knownQuote, missingQuote) stdout.println(`Available quote (one unset): ${availableQuote}`) // ============================================================ // PART 2: :=? GUARDED ASSIGNMENT — sets a variable if unset // ============================================================ // :=? assigns ONLY IF the target is unset price <- Money() minimumPrice <- 9.99#USD price :=? minimumPrice stdout.println(`Default price applied: ${price}`) // :=? with already-set target — assignment is skipped existingPrice <- 49.99#USD existingPrice :=? minimumPrice stdout.println(`Existing price preserved: ${existingPrice}`) // ============================================================ // PART 3: SAME TYPES, DIFFERENT OPERATIONS // ============================================================ // Both operations work on Date, but do different things: // <? picks the earlier of two dates dateA <- 2024-11-15 dateB <- 2024-11-08 earlierDate <- earlierOf(dateA, dateB) stdout.println(`Earlier date: ${earlierDate}`) // :=? sets a deadline only if none exists deadline <- Date() fallbackDate <- 2024-12-31 deadline :=? fallbackDate stdout.println(`Fallback deadline: ${deadline}`)
Other ways to ask this
- What is the distinction between <? and :=? in EK9?
- I keep confusing <? coalescing with :=? guarded assignment — show them side by side.
- In Java I mix up Math.min with null-check assignment. How are these separate in EK9?
- Show the two operators that look similar but do completely different things.
Coming from another language?
Java conflates these: Math.min(a, b) for comparison vs if (x == null) x = default for assignment — both need null checks. EK9 separates them cleanly: <? for comparison, :=? for conditional assignment. Each handles unset values automatically.
Keywords: contrast, <?, guarded, coalescing, comparison, distinction, assignment, :=?