Chain multiple fallback values to find the first one that is set.

← Operators and Expressions · Ref: Q1093

Chained fallback:

  port <- envPort ?: configPort ?: defaultPort

Evaluates left-to-right, returning the first set value in the chain. Works with any number of levels. See Q1091 for basic ?: coalescing, Q899 for all coalescing operators.

Example

defines module qa.operators.chainedcoalescing

  defines program

    ChainedCoalescingDemo()
      stdout <- Stdout()

      //First two unset — falls through to the third
      envPort <- Integer()
      configPort <- Integer()
      defaultPort <- 8080

      port <- envPort ?: configPort ?: defaultPort
      stdout.println(`Port: ${port}`)

      //Second is set — stops there
      envHost <- String()
      configHost <- "config.local"
      defaultHost <- "localhost"

      host <- envHost ?: configHost ?: defaultHost
      stdout.println(`Host: ${host}`)

Common mistakes

E01073 — EK9 has no 'null' - using it (here as a fallback value) is rejected with E01073; chain ?: over real set/unset values instead. See ek9 -h E01073 for details.

Incorrect:

port <- envPort ?: configPort ?: null

Correct:

port <- envPort ?: configPort ?: defaultPort
Other ways to ask this
  • I have three config sources and need the first available value from any of them
  • In JavaScript I'd chain ?? operators. Write the EK9 multi-level fallback
  • Given primary, secondary, and default values, return the first set one
  • Cascade through multiple optional values using chained ?: operators

Coming from another language?

JavaScript: a ?? b ?? c. Kotlin: a ?: b ?: c. Swift: a ?? b ?? c. EK9: a ?: b ?: c — identical chaining syntax.

Keywords: chained, coalescing, cascade, fallback, multiple, ?:, levels