Show me how to use :=? on a custom class field — give me a worked example where a UserSession class has a sessionToken that is set on first login and never overwritten.

← Operators and Expressions · Ref: Q1266

The :=? guarded assignment works on class fields just as it does on local variables. It is the natural way to implement set-once fields without writing manual 'is this set?' checks. (For data-only carriers without behaviour, use a record — but records cannot have methods, so this example uses a class because it needs a captureToken method.)

USERSESSION CLASS WITH SET-ONCE TOKEN

  UserSession
    userName as String: String()
    sessionToken as String: String()
    UserSession()
      -> userName as String
      this.userName :=: userName
    captureToken()
      -> token as String
      sessionToken :=? token
    default operator ?

The captureToken method uses :=? on the field. The first call sets sessionToken. Every subsequent call is silently ignored — the original token is preserved.

USAGE

  session <- UserSession("alice")
  // First login captures the token
  session.captureToken("abc-123-first")
  stdout.println(`after first login: ${session.currentToken()}`)
  // Subsequent logins do NOT replace the token
  session.captureToken("xyz-456-second")
  session.captureToken("def-789-third")
  stdout.println(`after more logins: ${session.currentToken()}`)

The sessionToken stays as 'abc-123-first' regardless of how many times captureToken is called.

WHY THIS IS BETTER THAN MANUAL CHECKS

You could write the same logic with an if-check:

  captureToken()
    -> token as String
    if not sessionToken?
      sessionToken: token

This works but is verbose and easy to get backwards. The :=? operator does the right thing in one symbol with no risk of missing the negation.

WHEN TO USE GUARDED ASSIGNMENT ON FIELDS

- Authentication tokens captured on first login
- Origin URLs captured on first redirect
- Created-at timestamps that should never change
- Cached computed values that should be set once
- Configuration that loads on first access

In all cases, the goal is 'first value wins, later values ignored'. :=? is the right tool.

See Q1263 for String guarded assignment. See Q1264 for Integer. See Q1265 for Date. See Q1226 for the contrast between :=? and <?.

Example

defines module qa.operators.guardedassignrecord

  defines class

    UserSession
      userName as String: String()
      sessionToken as String: String()

      UserSession()
        -> name as String
        this.userName :=: name

      captureToken()
        -> token as String
        sessionToken :=? token

      currentToken() as pure
        <- rtn as String: sessionToken

      default operator ?

  defines program

    GuardedAssignRecordDemo()
      stdout <- Stdout()

      session <- UserSession("alice")

      session.captureToken("abc-123-first")
      stdout.println(`after first login: ${session.currentToken()}`)

      session.captureToken("xyz-456-second")
      session.captureToken("def-789-third")
      stdout.println(`after more logins: ${session.currentToken()}`)

Common mistakes

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

Incorrect:

sessionToken.guardedSet(token)

Correct:

sessionToken :=? token
Other ways to ask this
  • How does :=? work inside a record method that sets a field once?
  • Give me a UserSession example using guarded assignment on a token field.
  • Use :=? on a custom record field for set-once semantics.
  • Show me a method that initialises a record field with :=? only when unset.

Coming from another language?

Java: if (sessionToken == null) sessionToken = token; — verbose. Kotlin: sessionToken = sessionToken ?: token — also works, but reassigns. Rust: sessionToken.get_or_insert(token); — standard library helper. Python: if self.sessionToken is None: self.sessionToken = token. EK9: sessionToken :=? token — single operator, in-place, idempotent.

Keywords: record field, first value wins, UserSession, :=?, guarded assignment, session token, set once