How do functions extend other functions in EK9?

← Function Extension · Ref: Q588

In EK9, functions are types that can participate in type hierarchies. A concrete function can extend an abstract function using 'is' or 'extends'. This creates function polymorphism without classes.

FUNCTION EXTENSION SYNTAX

Use 'is' to extend an abstract function:

  Transformer as pure abstract
    -> input as String
    <- result as String?
  UpperTransformer is Transformer as pure
    -> input as String
    <- result as String: input.upperCase()

WHY THIS IS UNIQUE

In most languages, callable polymorphism requires classes, interfaces, or trait objects. EK9 functions are TYPES with identity: they can be stored, passed, and collected in lists. Function extension gives you polymorphism without any class boilerplate.

SIGNATURE MATCHING

The extending function must match the abstract function's signature: same parameter types and compatible return type. Mismatches produce E05140.

See Q51 for abstract functions. See Q49 for function basics. See Q589 for abstract function implementations. See Q592 for signature mismatch errors.

Example

defines module qa.function.extensionbasics

  defines function

    //Abstract function: defines the contract
    Transformer as pure abstract
      -> input as String
      <- result as String?

    //Concrete function extends abstract
    UpperTransformer is Transformer as pure
      -> input as String
      <- result as String: input.upperCase()

    //Another implementation
    PrefixTransformer is Transformer as pure
      -> input as String
      <- result as String: "PREFIX:" + input

    //Yet another implementation
    LengthTransformer is Transformer as pure
      -> input as String
      <- result as String: $length input

  defines program

    FunctionExtensionBasicsDemo()
      stdout <- Stdout()

      //Direct calls
      stdout.println(UpperTransformer("hello"))
      stdout.println(PrefixTransformer("world"))
      stdout.println(LengthTransformer("test"))

      //Polymorphic use through abstract type
      transformers <- List() of Transformer
      transformers += UpperTransformer
      transformers += PrefixTransformer
      transformers += LengthTransformer

      for transformer in transformers
        stdout.println(transformer("ek9"))

Common mistakes

E05150 — When the abstract function is pure, all extending functions must also be pure. Omitting 'as pure' violates the purity contract and triggers E05150 because 'pure' in super requires 'pure' for the extending definition. See ek9 -h E05150 for details.

Incorrect:

UpperTransformer is Transformer
      -> input as String
      <- result as String: input.upperCase()

Correct:

UpperTransformer is Transformer as pure
      -> input as String
      <- result as String: input.upperCase()
Other ways to ask this
  • How does function inheritance work in EK9?
  • Can functions extend abstract functions?
  • What does 'is' mean for functions?

Coming from another language?

Java: functional interfaces + lambda, no function type hierarchies. Python: no function typing. Rust: Fn traits are structural, not nominal. Go: function types exist but no inheritance. Kotlin: functional types are structural. Swift: closures are structural types, extensions add methods to existing types but no function type hierarchies. EK9: functions are nominal types with 'is'/'extends' hierarchies, unique function polymorphism.

Keywords: type, function, polymorphism, extension, visitor, extends, extend, abstract, handler, is, sealed, swift, hierarchy