Why does EK9 reject a generic type named without 'of' in a declaration?

← Generics · Ref: Q1310

When a generic type such as List, Dict, Optional or Result appears in a type position - a parameter declaration, a return-value declaration, or a field/variable type - it must be fully parameterized with an 'of' clause. Naming the bare generic (e.g. 'as List') gives the compiler no element type to work with, so it raises E04080 (Template/Generic requires parameterization). The fix is to state the element type: 'as List of String', 'as Dict of (String, Integer)', 'as Optional of MyClass', or 'as Result of (Integer, String)'. This is distinct from E06010, which fires when a bare generic is constructed in an expression such as 'items <- List()'.

See Q194 for generic classes. See Q198 for built-in generics.

Example

defines module qa.generics.parameterization

  defines function

    //THE FIX: every generic in a type position carries an 'of' clause.
    //The parameter and the return value are both fully parameterized.
    headCount() as pure
      -> names as List of String
      <- rtn as Integer: length names

    //Dict in a parameter position needs both key and value types.
    lookupAge() as pure
      ->
        ages as Dict of (String, Integer)
        who as String
      <- rtn as Integer: ages.getOrDefault(who, Integer())

  defines program

    GenericParameterizationDemo()
      stdout <- Stdout()

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

      ages <- {"Alice": 30, "Bob": 25}
      stdout.println(`Age of Alice: ${lookupAge(ages, "Alice")}`)

Common mistakes

E04080 — Declaring a parameter as the bare generic 'List' gives the compiler no element type, so it raises E04080. A generic named in a type position (parameter, return value, or field) must be fully parameterized: add an 'of' clause such as 'as List of String'. See ek9 -h E04080 for details.

Incorrect:

headCount()
  -> names as List
  <- rtn as Integer: length names

Correct:

    headCount() as pure
      -> names as List of String
      <- rtn as Integer: length names
Other ways to ask this
  • What triggers E04080 TEMPLATE_TYPE_REQUIRES_PARAMETERIZATION?
  • Why can't I declare a parameter or variable just 'as List' in EK9?
  • How do I specify the element type when declaring a generic in EK9?

Coming from another language?

Java: 'List items' (raw type) compiles with only an unchecked warning, deferring failures to runtime ClassCastException. Kotlin/Swift: a bare generic in a type position is a compile error, matching EK9. Python: collections are untyped, so element type is never declared. EK9: a generic in any declaration position MUST be parameterized at compile time (E04080), there is no raw-type escape hatch.

Keywords: List, raw-type, Optional, declaration, of, parameterization, E04080, type-parameter, generic, parameterized, Dict