Write me an open logWriter function and a dynamic function instance that overrides its behaviour, demonstrating that 'as open' on a function allows dynamic instances to extend it.

← Functions and Methods · Ref: Q1252

FUNCTIONS in EK9 follow the same closed-by-default rule as classes. To allow a dynamic function instance to extend a concrete function, mark the function 'as open'. Without 'as open' the compiler raises E05030 when something tries to extend it.

OPEN CONCRETE FUNCTION

  logWriter() as open
    -> message as String
    <- formatted as String: "[default] " + message

The function has a body (default behaviour) AND is marked 'as open' so dynamic instances can override it.

DYNAMIC INSTANCE EXTENDING IT

  consoleVariant <- () is logWriter as function
    formatted: "[console] " + message

The '() is logWriter as function' creates a dynamic instance whose body replaces the default. The 'message' parameter and 'formatted' return variable come from the parent function's signature — they are visible inside the dynamic body.

USAGE

  defaultLine <- logWriter("hello")
  consoleLine <- consoleVariant("hello")
  stdout.println(defaultLine)
  stdout.println(consoleLine)
  // Output:
  // [default] hello
  // [console] hello

WHEN TO USE 'AS OPEN' ON A FUNCTION

Use it when you have a default implementation that works fine for most callers, but you want callers to be able to provide a specialised dynamic instance for specific needs. If you want to FORCE a custom implementation (no default), use 'as abstract' instead (see Q1253).

See Q1250 for 'as open' on classes. See Q1253 for 'as abstract' functions. See Q1043 for diagnosing E05030.

Example

defines module qa.functionsandmethods.openlogwriter

  defines function

    logWriter() as open
      -> message as String
      <- formatted as String: "[default] " + message

  defines program

    OpenLogWriterDemo()
      stdout <- Stdout()

      consoleVariant <- () is logWriter as function
        formatted: "[console] " + message

      defaultLine <- logWriter("hello")
      consoleLine <- consoleVariant("hello")
      stdout.println(defaultLine)
      stdout.println(consoleLine)

Common mistakes

E05030 — Without 'as open', the function is closed and dynamic instances cannot extend it. Add 'as open' to the parent function. See ek9 -h E05030 for details.

Incorrect:

logWriter()
      -> message as String
      <- formatted as String: "[default] " + message

Correct:

logWriter() as open
      -> message as String
      <- formatted as String: "[default] " + message
Other ways to ask this
  • How do I make a function extensible in EK9 with 'as open'?
  • Show me a concrete function with 'as open' that a dynamic function can extend.
  • Create a logWriter function that allows a dynamic instance to override its body.
  • I got E05030 on my function — how do I allow a dynamic instance to extend it?

Coming from another language?

Java: no standalone open functions, methods are open by default. Kotlin: top-level functions are not extensible. Python: functions can be reassigned but not 'extended'. EK9 is unusual in allowing function extension via 'as open' plus a dynamic instance — the parent function provides the default body, the dynamic instance overrides it.

Keywords: E05030, extend function, dynamic instance, logWriter, function, as open