What built-in generic types does EK9 provide?

← Generics · Ref: Q198

EK9 provides several built-in generic types. These are closed by default and cannot be extended. Use composition (wrapping) instead of inheritance.

LIST OF T

Ordered collection:

  names <- List() of String
  names += "Alice"

DICT OF (K, V)

Key-value mapping:

  ages <- Dict() of (String, Integer)

OPTIONAL OF T

May or may not contain a value:

  maybe <- Optional("hello")

RESULT OF (OK, ERR)

Success or error value:

  result <- Result(42) of (Integer, String)

ITERATOR OF T

Lazy sequence of values from .iterator() on collections.

MUTEXLOCK OF T

Thread-safe wrapper for concurrent access. Held as a FIELD on a wrapping class (locals are rejected by E08256). See Q158 for the canonical field-on-class pattern.

CLOSED BY DEFAULT

Built-in generics cannot be extended. Use composition:

  MyList             // CORRECT: wrap a List
    items as List of String

See Q45 for List. See Q46 for Dict. See Q47 for Optional. See Q48 for Result. See Q128 for closed collections. See Q158 for MutexLock.

Example

defines module qa.generics.builtin

  defines program

    BuiltinGenericsDemo()
      stdout <- Stdout()

      // === LIST OF T ===

      names <- List() of String
      names += "Alice"
      names += "Bob"
      stdout.println(`List size: ${length names}`)

      // === DICT OF (K, V) ===

      ages <- {"Alice": 30, "Bob": 25}
      stdout.println(`Dict size: ${length ages}`)

      // === OPTIONAL OF T ===

      maybe <- Optional("hello")
      if maybe?
        stdout.println(`Optional has value: ${maybe}`)

      emptyOpt <- Optional() of String
      stdout.println(`Empty optional set: ${emptyOpt?}`)

      // === RESULT OF (OK, ERR) ===

      okResult <- Result("Success", Integer())
      stdout.println(`Result is ok: ${okResult?}`)

      // === MUTEXLOCK OF T ===
      // MutexLock must be a FIELD on a wrapping class — see Q158 and Q213
      // for the canonical pattern. Locals are rejected (E08256).

      stdout.println("MutexLock of T — see Q158 for the field-on-class pattern")

      // === CANNOT EXTEND (CLOSED) ===
      // MyList extends List of String  // ERROR: not open
      // Use composition instead:
      //   MyList
      //     items as List of String

      stdout.println("Built-in generics are closed, use composition")

Common mistakes

E06020 — List takes one type parameter T. Providing two type arguments does not match the generic definition. See ek9 -h E06020 for details.

Incorrect:

names <- List() of (String, Integer)

Correct:

names <- List() of String
Other ways to ask this
  • What parameterized types come with EK9?
  • Which generic containers does EK9 have?
  • Can I extend built-in generic types in EK9?

Coming from another language?

Java: ArrayList<T>, HashMap<K,V>, Optional<T> are all open to extension. Python: list, dict are open. Rust: Vec<T>, HashMap<K,V> cannot be inherited (no inheritance). Go: slices and maps are built-in, no generics before 1.18. Kotlin: List<T>, Map<K,V> are interfaces. EK9: List, Dict, Optional, Result, MutexLock are closed generic types, use composition pattern.

Keywords: safe, iterator, priorityqueue, mutexlock, error, guard, optional, list, result, ok, absent, parameterized, dict, generic, type-parameter, built-in