What is the consistent safe-access pattern across all EK9 types?

← Safe Value Access · Ref: Q166

EK9 provides a consistent safe-access pattern across Dict, List, Optional, and Result. The same mental model applies everywhere: provide a default, get a usable value.

DICT: GETORDEFAULT WITH KEY

  dict.getOrDefault(key, default)

Lookup by key with fallback.

LIST: GETORDEFAULT WITH INDEX

  list.getOrDefault(index, default)

Lookup by position with fallback.

OPTIONAL: GETORDEFAULT

  optional.getOrDefault(default)

Extract contained value or use fallback.

RESULT: OKORDEFAULT / ERRORORDEFAULT

  result.okOrDefault(default)
  result.errorOrDefault(default)

Extract ok or error value with fallback.

GUARD PATTERN

All types support the ? operator for guard checks:

  if dict contains key then access
  if opt? then opt.get()
  if result.isOk() then result.ok()

WHY CONSISTENCY MATTERS

One pattern to learn, works everywhere. No need to remember different APIs for different container types. New developers learn the pattern once and apply it across the entire language.

See Q161 for Dict safe access. See Q162 for List safe access. See Q163 for Optional unwrap. See Q164 for Result extraction. See Q165 for why there is no .get() method.

Example

defines module qa.safeaccess.consistentpattern

  defines program
    ConsistentPatternDemo()
      stdout <- Stdout()

      // === DICT: getOrDefault(key, default) ===

      config <- {"host": "localhost", "port": "8080"}
      host <- config.getOrDefault("host", "127.0.0.1")
      timeout <- config.getOrDefault("timeout", "30")
      stdout.println(`Host: ${host}`)
      stdout.println(`Timeout (default): ${timeout}`)

      // === LIST: getOrDefault(index, default) ===

      args <- ["run", "test", "verbose"]
      command <- args.getOrDefault(0, "help")
      missing <- args.getOrDefault(10, "none")
      stdout.println(`Command: ${command}`)
      stdout.println(`Missing arg: ${missing}`)

      // === OPTIONAL: getOrDefault(default) ===

      userName <- Optional("Steve")
      displayName <- userName.getOrDefault("Anonymous")
      stdout.println(`User: ${displayName}`)

      noUser <- Optional() of String
      fallbackName <- noUser.getOrDefault("Anonymous")
      stdout.println(`No user: ${fallbackName}`)

      // === RESULT: okOrDefault(default) ===

      okResult <- Result("Data loaded", Integer())
      msg <- okResult.okOrDefault("No data")
      stdout.println(`Result msg: ${msg}`)

      errResult <- Result(String(), 404)
      errMsg <- errResult.okOrDefault("No data")
      stdout.println(`Error result msg: ${errMsg}`)

      errCode <- errResult.errorOrDefault(0)
      stdout.println(`Error code: ${errCode}`)

Common mistakes

E50060 — Dict does not have a .get() method. Use getOrDefault() with a fallback value. Calling a non-existent method triggers E50060 — method not resolved. See ek9 -h E50060 for details.

Incorrect:

host <- config.get("host")

Correct:

host <- config.getOrDefault("host", "127.0.0.1")

E08030 — Optional.get() requires a ? guard check first. Calling .get() without checking triggers E08030 — has not been checked before access. Use getOrDefault() for guard-free access. See ek9 -h E08030 for details.

Incorrect:

displayName <- userName.get()

Correct:

displayName <- userName.getOrDefault("Anonymous")
Other ways to ask this
  • How do I use the same safe access pattern on Dict, List, Optional, and Result?
  • Is there a unified way to safely access values in EK9?
  • How does getOrDefault work across different EK9 types?

Coming from another language?

Java: different APIs per type (Map.get, List.get, Optional.orElse, no Result). Python: dict.get(), list[i] (throws), no Optional. Rust: HashMap.get() returns Option, Vec.get() returns Option, unified Option/Result but different APIs. Go: comma-ok for maps, panic for slices, no Optional/Result. Kotlin: different null-safe operators per context. EK9: getOrDefault() everywhere, one pattern for all container types.

Keywords: access, guard, getOrDefault, error, safe, pattern, consistent, unified, null-safe, dict, isset, absent, ok, result, list, optional