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

#!ek9
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, as open, dynamic instance, extend function, function, logWriter