How do I provide a default value when something might be unset in EK9?

← Control Flow · Ref: Q985

EK9 provides two operators for default values:

?: COALESCE (ELVIS)

Returns the left value if SET, otherwise the right:

  displayName <- userName ?: "Guest"
  timeout <- configuredTimeout ?: defaultTimeout

:=? ASSIGN-IF-UNSET

Only assigns if the target is currently UNSET:

  serverHost <- String()
  serverHost :=? "localhost"
  serverHost :=? "other"     has no effect — already set to localhost

WHEN TO USE EACH

?: when creating a new variable with a fallback.
:=? when conditionally initialising an existing variable.

COMBINING WITH GUARDS

  if connection <- tryConnect(primaryHost)
    useConnection(connection)
  else
    fallbackHost <- primaryHost ?: backupHost
    if backup <- tryConnect(fallbackHost)
      useConnection(backup)

NO ?? OPERATOR

EK9 has no ?? (null coalescing) operator (E01096). An unset value such as String() is present but has no meaning, and ?: is what gives it a default:

  name <- String()
  name ?: "Guest"       "Guest"

See Q1059 for why ?? does not exist.

Example

#!ek9
defines module qa.controlflow.defaultvalue

  defines function

    lookupSetting() as pure
      -> settingName as String
      <- rtn as String: String()

      if settingName == "host"
        rtn: "production.example.com"

  defines program

    DefaultValueDemo()
      stdout <- Stdout()

      // ?: for inline defaults
      configuredHost <- lookupSetting("host")
      activeHost <- configuredHost ?: "localhost"
      stdout.println(`Host: ${activeHost}`)

      // ?: when lookup returns unset
      missingPort <- lookupSetting("port")
      activePort <- missingPort ?: "8080"
      stdout.println(`Port: ${activePort}`)

      // :=? for conditional initialisation
      logLevel <- lookupSetting("logLevel")
      logLevel :=? "INFO"
      stdout.println(`Log level: ${logLevel}`)

      // :=? has no effect when already set
      logLevel :=? "DEBUG"
      stdout.println(`Still: ${logLevel}`)
Other ways to ask this
  • How do I fall back to a default in EK9?
  • What is the EK9 equivalent of a default value expression?
  • Which operator gives an unset value a default in EK9 - I know ?? from other languages?
  • How do I use :=? for conditional initialisation?

Coming from another language?

EK9 uses ?: (elvis) for an inline default and :=? for assign-if-unset. Both handle unset values without any concept of null. Unlike C#/Swift/JavaScript, EK9 has no ?? (E01096): ?: is the one operator that defaults an unset value.

Keywords: coalescing, default, fallback, guarded, unset