Why must generic functions provide an implementation?
← Generics · Ref: Q649
EK9 requires generic functions to provide an implementation. Unlike abstract methods in classes, generic functions are templates that must contain code to execute when instantiated.
IMPLEMENTATION REQUIRED
A generic function must have a body:
transform() of type T as open -> item as T <- rtn as T: T(item)
The body provides the default behavior.
AS OPEN FOR EXTENSION
Mark a generic function 'as open' to allow specialised implementations:
compare() of type T as open -> a as T, b as T <- rtn as Integer: a <=> b
Concreted implementations can override this default.
DYNAMIC INSTANTIATION
Generic functions create concrete instances:
intCompare <- () is compare of Integer as function
This uses the template's default implementation.
CUSTOM IMPLEMENTATION
Dynamic functions can provide custom bodies:
customCompare <- () is compare of Integer as function rtn: b <=> a // reversed
See Q197 for extending generics. See Q647 for function constraint rules. See Q194 for generic class basics.
Example
defines module qa.genericsdeep.functionimplementation defines function <?- Correct: generic function with implementation body. 'as open' allows extension when parameterised. -?> doubleValue() of type T as open -> item as T <- rtn as T: item + item <?- Correct: multi-param generic function with body. -?> selectFirst() of type (A, B) as open -> first as A second as B <- rtn as A: A(first) require second? <?- Correct: constrained generic function with implementation. -?> stringify() of type T as open -> item as T <- rtn as String: $item defines program GenericFunctionImplDemo() stdout <- Stdout() // === USING DEFAULT IMPLEMENTATIONS === doubled <- doubleValue(21) stdout.println(`Doubled: ${doubled}`) strDoubled <- doubleValue("ab") stdout.println(`String doubled: ${strDoubled}`) // === MULTI-PARAM GENERIC FUNCTION === selected <- selectFirst("chosen", 99) stdout.println(`Selected: ${selected}`) // === STRINGIFY GENERIC === asStr <- stringify(3.14) stdout.println(`Stringified: ${asStr}`)
Common mistakes
E07110 — Generic functions must provide an implementation body. Unlike abstract methods in classes, generic functions are templates that generate concrete code when instantiated with specific types. A generic function without a body has nothing to instantiate. See ek9 -h E07110 for details.
Incorrect:
doubleValue() of type T as open -> item as T <- rtn as T?
Correct:
doubleValue() of type T as open -> item as T <- rtn as T: item + item
Other ways to ask this
- What is E06100 generic function implementation required?
- Can I declare a generic function without a body?
- How do generic function templates work in EK9?
Coming from another language?
Java: abstract methods exist but generic methods always have bodies. C++: templates always have bodies (no separate declaration for function templates). Rust: generic functions always have bodies. Go: generic functions always have bodies. Kotlin: generic functions always have bodies. EK9: same requirement, enforced with E06100 if body missing.
Keywords: function, open, implementation, type-parameter, required, E06100, generic, template, body