How can I record a 'first seen' Date that is set on the first observation and never overwritten on subsequent observations, using :=?

← Operators and Expressions · Ref: Q1265

The :=? guarded assignment operator is ideal for 'first seen' or 'first occurrence' patterns where you want to capture the FIRST value and ignore any later updates. It works on Date the same way it works on every other type — assign only if the target is unset.

WORKED EXAMPLE: FIRST SEEN DATE

  firstSeen as Date: Date()        // unset
  // First observation: assigned because firstSeen was unset
  firstSeen :=? 2025-03-10
  stdout.println(`first :=? -> ${firstSeen}`)
  // Later observations: SKIPPED because firstSeen is now set
  firstSeen :=? 2025-04-15
  firstSeen :=? 2025-05-20
  stdout.println(`final firstSeen -> ${firstSeen}`)

The value remains 2025-03-10 throughout. The 'first seen' semantics are exactly what :=? provides — there is no need for an external 'has been seen' flag.

WHY THIS IS USEFUL

- Audit trails: record when a record was first created
- Caches: store the first computed value, never recompute
- Logs: capture the timestamp of the first error in a session
- Statistics: track the start time of an aggregation window

IN ALL THESE CASES, you want the FIRST value to win and all later values to be silently dropped. :=? does this in one line.

ALTERNATIVE WITHOUT :=?

  if not firstSeen?
    firstSeen: 2025-03-10

This works but is verbose. The :=? operator collapses the check and assignment into one symbol.

See Q1263 for String guarded assignment. See Q1264 for Integer. See Q1266 for custom record. See Q1226 for the contrast between :=? and <?.

Example

defines module qa.operators.guardedassigndate

  defines program

    GuardedAssignDateDemo()
      stdout <- Stdout()

      firstSeen as Date: Date()
      firstSeen :=? 2025-03-10
      stdout.println(`first :=? -> ${firstSeen}`)

      firstSeen :=? 2025-04-15
      firstSeen :=? 2025-05-20
      stdout.println(`final firstSeen -> ${firstSeen}`)

Common mistakes

E50060 — Date does not have a setIfAbsent method. The :=? operator is the correct way to perform guarded assignment — it assigns only when the target is unset. See ek9 -h E50060 for details.

Incorrect:

firstSeen.setIfAbsent(2025-03-10)

Correct:

firstSeen :=? 2025-03-10
Other ways to ask this
  • Record a Date only on the first call without overwriting on later calls.
  • How do I implement 'first seen' semantics for a Date field?
  • Show me :=? on a Date variable.
  • Set a Date once and ignore later attempts to change it.

Coming from another language?

Java: if (firstSeen == null) firstSeen = LocalDate.of(2025, 3, 10). Kotlin: firstSeen = firstSeen ?: LocalDate.of(2025, 3, 10). Python: firstSeen = firstSeen or date(2025, 3, 10) — but this conflates falsy with None. Rust: firstSeen.get_or_insert(NaiveDate::from_ymd_opt(2025, 3, 10).unwrap()). EK9: firstSeen :=? 2025-03-10 — direct, single line, type-safe Date literal.

Keywords: first occurrence, set once, audit, guarded assignment, :=?, Date, first seen