Question: Wire an application with all dependencies correctly to pass compile-time DI validation.

I need to ensure my DI wiring passes the compiler's completeness check

In Spring a missing bean crashes at runtime. Show how EK9 catches it at compile time

Given a service that injects two dependencies, register everything so the compiler is satisfied

Demonstrate that EK9 validates all injection points before the program can run

Answer:
The compiler performs four DI validations:

  register ConsoleLogger() as Logger
  register AppService() as Service

1. Completeness -- every ! field has a matching registration. 2. Ordering -- dependencies before dependents. 3. Cycle detection (E08190). 4. Field count limits (E11040). If it compiles, all injection points are guaranteed satisfied.

See Q227 for DI validation details. See Q229 for circular dependency detection.

defines module qa.di.compilevalidation

  defines component

    Logger as abstract
      log() as abstract
        -> message as String
        <- output as String?
      default operator ?

    ConsoleLogger is Logger
      override log()
        -> message as String
        <- output as String: `[OK] ${message}`
      default operator ?

    Service as abstract
      run() as abstract
        <- output as String?
      default operator ?

    AppService is Service
      logger as Logger!

      override run()
        <- output <- String()
        output: logger.log("DI validated at compile time")

      default operator ?

  defines application

    ValidatedApp
      //Compiler validates: Logger before AppService, all ! fields satisfied
      register ConsoleLogger() as Logger
      register AppService() as Service

  defines program

    DiCompileValidationDemo() with application of ValidatedApp
      stdout <- Stdout()
      service as Service!
      result <- service.run()
      stdout.println(result)

Spring: NoSuchBeanDefinitionException at runtime. Guice: CreationException at injector creation. EK9: compile error — the program cannot compile if DI is wrong.

DI compile completeness ordering safety validate

Explanation: Every injected component (Logger!) must have a matching 'register ... as' entry or the compiler rejects the incomplete wiring. See ek9 -h E08210 for details.


Question: Create an aspect that transparently proxies a component's method call.

I need to wrap a component with an aspect that passes calls through unchanged

In AspectJ I'd define a pointcut. Write the EK9 basic aspect

Given a concrete component, register it with a silent aspect proxy

Set up basic aspect delegation where calls pass through to the real component

Answer:
Extend Aspect and register with 'with aspect of':

  SilentAspect extends Aspect
    default operator ?
  ...
  register ConcreteComp() as AbstractComp with aspect of SilentAspect()

A silent aspect (no overridden advice) passes all calls through to the real component.

See Q1116 for aspects with constructor args. See Q1117 for exception handling.

defines module qa.designpatterns.aspectbasic

  defines component

    Worker as abstract
      doWork()
        <- rtn as String: "AbstractWorker"

    ConcreteWorker is Worker
      override doWork()
        <- rtn as String: "ConcreteWorker"

  defines class

    SilentAspect extends Aspect
      default operator ?

  defines application

    AspectApp
      register ConcreteWorker() as Worker with aspect of SilentAspect()

  defines program

    AspectBasicDemo() with application of AspectApp
      stdout <- Stdout()
      worker as Worker!
      result <- worker.doWork()
      stdout.println(result)

AspectJ: @Aspect + @Around. Spring AOP: @Aspect + @Before/@After. Python: decorators. EK9: extends Aspect + 'with aspect of' in registration.

AOP aspect delegation proxy transparent wrap

@Aspect register ConcreteWorker() as Worker with aspect of SilentAspect()

Explanation: EK9 has no '@'-annotations — '@Aspect' is parsed as an invalid directive; apply an aspect with 'with aspect of AspectClass()' in the register statement. See ek9 -h E50200 for details.

Oracle can generate an aspect that proxies a component method call.


Question: Create an aspect that takes a label in its constructor for identification.

I need an aspect with configurable state passed through its constructor

In Spring AOP I'd use @Aspect with fields. Write the EK9 aspect with constructor args

Given an aspect that needs a name, pass it via the constructor at registration

Build a parameterised aspect that carries configuration

Answer:
Aspects are classes with constructors and fields:

  LabelledAspect extends Aspect
    label <- String()
    LabelledAspect()
      -> label as String
      this.label :=: label
  ...
  register Impl() as Abstract with aspect of LabelledAspect("audit")

Pass constructor arguments at registration time.

See Q1115 for basic aspect. See Q1117 for exception handling.

defines module qa.designpatterns.aspectconstructor

  defines component

    Printer as abstract
      print()
        <- rtn as String: "AbstractPrinter"

    ConcretePrinter is Printer
      override print()
        <- rtn as String: "ConcretePrinter"

  defines class

    LabelledAspect extends Aspect
      label <- String()

      LabelledAspect()
        -> label as String
        this.label :=: label

      default operator ?

  defines application

    AspectConstructorApp
      register ConcretePrinter() as Printer with aspect of LabelledAspect("audit")

  defines program

    AspectConstructorDemo() with application of AspectConstructorApp
      stdout <- Stdout()
      printer as Printer!
      result <- printer.print()
      stdout.println(result)

Spring AOP: @Aspect class with @Value injection. AspectJ: aspect with constructor. EK9: Aspect subclass with constructor, configured at registration.

AOP aspect configuration constructor parameters

aspect with constructor
parameterised aspect


Question: Handle an exception that occurs inside an aspect-proxied component call.

I need to understand what happens when a proxied method throws through an aspect

In Spring AOP exceptions propagate through advice. Show the EK9 aspect exception path

Given a component that throws, verify the exception passes through the aspect to the caller

Test exception propagation through an aspect proxy

Answer:
Exceptions propagate through aspects unchanged:

  calc as Calculator!
  result <- calc.divide(10)

A silent aspect does not catch or modify exceptions -- they pass straight through. The caller's try/catch handles exceptions as if no aspect were present.

See Q1115 for basic aspect. See Q1116 for aspect with constructor.

defines module qa.designpatterns.aspectexception

  defines component

    Calculator as abstract
      divide() as abstract
        -> divisor as Integer
        <- result as Integer?

    SafeCalculator is Calculator
      override divide()
        -> divisor as Integer
        <- result as Integer: 100 / divisor

  defines class

    AuditAspect extends Aspect
      default operator ?

  defines application

    ExceptionApp
      register SafeCalculator() as Calculator with aspect of AuditAspect()

  defines program

    AspectExceptionDemo() with application of ExceptionApp
      stdout <- Stdout()
      calc as Calculator!

      //Normal call through aspect
      result <- calc.divide(10)
      stdout.println(`100 / 10 = ${result}`)

Spring AOP: exceptions propagate through @Around advice unless caught. AspectJ: same propagation. EK9: same — exceptions pass through the aspect proxy transparently.

aspect
error
exception
propagate
proxy
try catch

aspect exception handling
exception propagation


Question: Apply an aspect to a component that has multiple methods.

I have a component with start, stop, and status methods — apply an aspect to all of them

In AspectJ a pointcut can match multiple methods. Show the EK9 multi-method aspect

Given a service with several methods, wrap all of them with a single aspect

Verify that an aspect proxies every method on a component, not just one

Answer:
An aspect proxies ALL component methods:

  service.start()
  service.status()
  service.stop()

Every method call goes through the aspect proxy. A silent aspect forwards all calls unchanged.

See Q1115 for basic aspect. See Q1119 for aspect ordering.

defines module qa.designpatterns.aspectmultiplemethods

  defines component

    Service as abstract
      start()
        <- rtn as String: "abstract-start"

      stop()
        <- rtn as String: "abstract-stop"

      status()
        <- rtn as String: "abstract-status"

    ServiceImpl is Service
      override start()
        <- rtn as String: "started"

      override stop()
        <- rtn as String: "stopped"

      override status()
        <- rtn as String: "running"

  defines class

    SilentAspect extends Aspect
      default operator ?

  defines application

    MultiMethodApp
      register ServiceImpl() as Service with aspect of SilentAspect()

  defines program

    AspectMultipleMethodsDemo() with application of MultiMethodApp
      stdout <- Stdout()
      service as Service!

      //All three methods go through the aspect
      stdout.println(service.start())
      stdout.println(service.status())
      stdout.println(service.stop())

Spring AOP: pointcut expressions select methods. AspectJ: wildcards in pointcuts. EK9: aspects apply to ALL methods on the registered component automatically.


Question: Register a component with an aspect and verify the aspect proxy is transparent.

I want to confirm that an aspect does not change the return value of a method

Show that a silent aspect passes method results through unchanged

Given two registrations — one with aspect, one without — verify identical results

Demonstrate aspect transparency by comparing proxied and direct calls

Answer:
A silent aspect is transparent -- calls and returns pass through unchanged:

  greeter as Greeter!
  result <- greeter.greet("World")

The caller cannot tell whether an aspect is present. This is the foundation of AOP in EK9.

See Q1115 for basic aspect. See Q1120 for no-aspect baseline.

defines module qa.designpatterns.aspectordering

  defines component

    Greeter as abstract
      greet() as abstract
        -> name as String
        <- rtn as String?

    SimpleGreeter is Greeter
      override greet()
        -> name as String
        <- rtn as String: `Hello ${name}`

  defines class

    TransparentAspect extends Aspect
      default operator ?

  defines application

    AspectOrderApp
      register SimpleGreeter() as Greeter with aspect of TransparentAspect()

  defines program

    AspectOrderingDemo() with application of AspectOrderApp
      stdout <- Stdout()
      greeter as Greeter!
      result <- greeter.greet("World")
      stdout.println(result)

Spring AOP: @Around that calls proceed() is transparent. AspectJ: proceed() in around advice. EK9: silent Aspect subclass — transparent by default.

aspect ordering proxy transparent unchanged

    TransparentAspect extends Aspect
      @Around proceed()

Explanation: EK9 has no Java/Spring-style annotations; the '@' prefix is reserved for compiler directives and '@Around' is not a valid one. See ek9 -h E50200 for details.


Question: Register a component without an aspect to show the baseline behaviour.

I want to see how a component behaves without any aspect wrapping

Show the difference between registering with and without an aspect

Given a service, register it directly without 'with aspect of'

Demonstrate a plain component registration for comparison with aspect examples

Answer:
Register without 'with aspect of' for direct access:

  register DirectWorker() as Worker

No proxy, no interception -- method calls go straight to the implementation. Use aspects only when you need cross-cutting behaviour.

See Q1115 for aspect basics. See Q1110 for register/inject.

defines module qa.designpatterns.noaspect

  defines component

    Worker as abstract
      doWork()
        <- rtn as String: "abstract"

    DirectWorker is Worker
      override doWork()
        <- rtn as String: "direct result"

  defines application

    NoAspectApp
      //No aspect — direct access
      register DirectWorker() as Worker

  defines program

    NoAspectDemo() with application of NoAspectApp
      stdout <- Stdout()
      worker as Worker!
      result <- worker.doWork()
      stdout.println(result)

Spring: @Service without @Aspect is the default. EK9: register without 'with aspect of' is the default.

baseline
direct
no aspect
plain
registration

register DirectWorker() as Worker with aspect of NoAspect()

Explanation: No need to invent a placeholder aspect — 'with aspect of NoAspect()' references an undefined aspect that fails to resolve; simply omit 'with aspect of' for direct registration. See ek9 -h E50001 for details.


Question: Write a dispatcher over a sealed Shape hierarchy with Circle, Square, and Triangle.

I need to handle different shape types without instanceof or casting

In Java I'd use instanceof checks or visitor pattern. Write the EK9 dispatcher

Given a sealed trait with three permitted types, dispatch on each type at runtime

Replace a chain of type checks with EK9's dispatcher mechanism

Answer:
Define sealed trait, then dispatcher method with overloads:

  describe() as dispatcher
    -> shape as Shape
    <- rtn as String: "Unknown"

  describe()
    -> shape as Circle
    <- rtn as String: "Circle"

Mark the base method 'as dispatcher'. The compiler generates dispatch logic -- no instanceof, no casting.

See Q1122 for dispatcher with fallback. See Q1123 for deep hierarchy.

defines module qa.designpatterns.dispatchersealed

  defines trait

    Shape allow only Circle, Square, Triangle
      name() as abstract
        <- rtn as String?

  defines class

    Circle with trait of Shape
      override name()
        <- rtn as String: "Circle"

    Square with trait of Shape
      override name()
        <- rtn as String: "Square"

    Triangle with trait of Shape
      override name()
        <- rtn as String: "Triangle"

    ShapeProcessor

      describe() as dispatcher
        -> shape as Shape
        <- rtn as String: "Unknown"

      describe()
        -> shape as Circle
        <- rtn as String: "Handled Circle"

      describe()
        -> shape as Square
        <- rtn as String: "Handled Square"

      describe()
        -> shape as Triangle
        <- rtn as String: "Handled Triangle"

  defines program

    DispatcherSealedDemo()
      stdout <- Stdout()
      processor <- ShapeProcessor()

      stdout.println(processor.describe(Circle()))
      stdout.println(processor.describe(Square()))
      stdout.println(processor.describe(Triangle()))

Java: instanceof + cast chain or visitor pattern. Kotlin: sealed class + when. Rust: enum + match. EK9: sealed trait + dispatcher — compiler generates dispatch, no casting.

dispatcher
pattern matching
sealed
switch
trait
type

dispatcher pattern
sealed trait dispatch

Explanation: EK9 has no instanceof. Use 'as dispatcher' to dispatch on runtime types.

Oracle can generate a dispatcher over a sealed type hierarchy with handler methods.


Question: Write a dispatcher with a fallback handler for unmatched types.

I need a dispatcher that handles known types and has a default for everything else

In Java I'd use a default case in a switch. Write the EK9 dispatcher default handler

Given an open hierarchy, dispatch known types and fall back for unknown ones

Handle specific types with dedicated handlers and catch-all for the rest

Answer:
The base dispatcher method IS the fallback:

  describe() as dispatcher
    -> shape as Shape
    <- rtn as String: "Unknown shape"

If no specific overload matches the runtime type, the base method runs. For sealed traits with exhaustive handlers, the fallback is never reached.

See Q1121 for sealed trait dispatch. See Q1123 for deep hierarchy.

defines module qa.designpatterns.dispatcherfallback

  defines class

    Shape as open
      name()
        <- rtn as String: "Shape"

    Circle extends Shape
      override name()
        <- rtn as String: "Circle"

    Square extends Shape
      override name()
        <- rtn as String: "Square"

    //No specific handler for this type — falls through to base
    Hexagon extends Shape
      override name()
        <- rtn as String: "Hexagon"

    ShapeDescriber

      describe() as dispatcher
        -> shape as Shape
        <- rtn as String: "Unknown shape"

      describe()
        -> shape as Circle
        <- rtn as String: "It is a Circle"

      describe()
        -> shape as Square
        <- rtn as String: "It is a Square"

  defines program

    DispatcherFallbackDemo()
      stdout <- Stdout()
      describer <- ShapeDescriber()

      //Matched handlers
      stdout.println(describer.describe(Circle()))
      stdout.println(describer.describe(Square()))

      //Fallback — no specific handler for Hexagon
      stdout.println(describer.describe(Hexagon()))

Java: switch default case or else branch. Kotlin: sealed when + else. EK9: the dispatcher base method is the default — no separate 'default' keyword needed.

catch-all default dispatcher fallback unmatched

      describe() as dispatcher
        -> shape as Shape
        <- rtn as String?
        default:
          rtn: "Unknown"

Explanation: The dispatcher base method IS the fallback. No 'default:' keyword — just provide the default return value.


Question: Dispatch on a deep class hierarchy where exact match wins over parent handler.

I have Shape -> Polygon -> Quadrilateral -> Square and need the most specific handler

In Java I'd check instanceof in order. Show how EK9 dispatcher picks the best match

Given a deep hierarchy, verify that a Square handler wins over a Polygon handler

Set up dispatcher resolution across multiple inheritance levels

Answer:
Most specific handler wins via cost-based selection:

  render() as dispatcher -> shape as Shape
  render() -> shape as Polygon
  render() -> shape as Square

Passing Quadrilateral selects Polygon handler (closest match). Passing Square selects Square handler (exact), not Polygon.

See Q1121 for sealed dispatch. See Q1122 for fallback handling.

defines module qa.designpatterns.dispatcherdeep

  defines class

    Shape as abstract
      default operator ?

    Polygon is Shape as open
      default operator ?

    Quadrilateral is Polygon as open
      default operator ?

    Square is Quadrilateral
      default operator ?

    GeometryRenderer

      render() as dispatcher
        -> shape as Shape
        <- rtn as String: "Shape handler"

      render()
        -> shape as Polygon
        <- rtn as String: "Polygon handler"

      render()
        -> shape as Square
        <- rtn as String: "Square handler"

  defines program

    DispatcherDeepDemo()
      stdout <- Stdout()
      renderer <- GeometryRenderer()

      //Polygon -> Polygon handler
      stdout.println(renderer.render(Polygon()))

      //Quadrilateral -> Polygon handler (closest match)
      stdout.println(renderer.render(Quadrilateral()))

      //Square -> Square handler (exact match beats Polygon)
      stdout.println(renderer.render(Square()))

Java: ordered instanceof checks (fragile). C#: pattern matching with type guards. EK9: dispatcher with automatic cost-based resolution — most specific handler wins.

cost-based deep dispatcher hierarchy resolution specific

deep hierarchy dispatch
cost-based resolution

Explanation: EK9 has no instanceof. The dispatcher automatically selects the most specific handler.


Question: Dispatch on two parameters to handle different shape combinations.

I need to handle Circle+Circle differently from Circle+Rectangle interactions

In Java I'd use the visitor pattern for double dispatch. Write the EK9 two-param dispatcher

Given two Shape parameters, select the correct handler based on both runtime types

Set up a dispatcher that dispatches on two parameter types simultaneously

Answer:
Multi-parameter dispatch -- parameter order matters:

  combine() as dispatcher
    -> s1 as Shape, s2 as Shape
    <- rtn as String: "Generic"

  combine() -> s1 as Circle, s2 as Circle
    <- rtn as String: "Circle-Circle"

Circle+Rectangle has a handler but Rectangle+Circle falls through to generic.

See Q1121 for single-param dispatch. See Q1123 for deep hierarchy.

defines module qa.designpatterns.dispatchertwoparam

  defines class

    Shape as abstract
      default operator ?

    Circle is Shape
      default operator ?

    Rectangle is Shape
      default operator ?

    Combiner

      combine() as dispatcher
        ->
          s1 as Shape
          s2 as Shape
        <- rtn as String: "Generic"

      combine()
        ->
          s1 as Circle
          s2 as Circle
        <- rtn as String: "Circle-Circle"

      combine()
        ->
          s1 as Circle
          s2 as Rectangle
        <- rtn as String: "Circle-Rectangle"

  defines program

    DispatcherTwoParamDemo()
      stdout <- Stdout()
      combiner <- Combiner()

      circle <- Circle()
      rectangle <- Rectangle()

      stdout.println(combiner.combine(circle, circle))
      stdout.println(combiner.combine(circle, rectangle))
      //Rectangle+Circle has no specific handler — falls to Generic
      stdout.println(combiner.combine(rectangle, circle))

Java: double dispatch via visitor pattern (complex). Kotlin: no built-in. EK9: two-param dispatcher — direct multi-dispatch without visitor boilerplate.

dispatcher
double dispatch
multi-dispatch
two parameter
visitor

      combine() as dispatcher
        ->
          s1 as Shape

Explanation: EK9 uses separate parameter lines. Mark the base method 'as dispatcher' with both parameters.


Question: Create a dynamic function that captures a prefix variable and prepends it to input.

I need a closure that captures a local variable and uses it in its body

In JavaScript I'd create a closure over a variable. Write the EK9 dynamic function

Given a prefix string, create a dynamic function that adds it to any input

Build a function that captures state with named capture syntax

Answer:
Capture a variable into a dynamic function:

  transform <- (prefix: prefixText) extends Transformer as function
    output: `${prefix} ${input}`

(prefix: prefixText) captures local 'prefixText' into a field named 'prefix'. The abstract function type defines parameter and return types.

See Q1126 for dynamic classes.

defines module qa.advancedtypes.dynamicfunctioncapture

  defines function

    Transformer as abstract
      -> input as String
      <- output as String?

  defines program

    DynamicFunctionCaptureDemo()
      stdout <- Stdout()
      prefixText <- "Hey"

      //Create dynamic function capturing prefixText as 'prefix'
      transform <- (prefix: prefixText) extends Transformer as function
        output: `${prefix} ${input}`

      result <- transform("World")
      stdout.println(result)

JavaScript: const fn = (input) => prefix + input (closure). Java: lambda with effectively final variable. Python: lambda or closure. EK9: named capture in dynamic function.

capture closure dynamic function lambda state

Explanation: EK9 dynamic functions extend an abstract function type. Use 'extends TypeName as function' with a capture list.


Question: Create a dynamic class that implements a Describable trait inline.

I need an anonymous class implementing a trait, created inline with captured state

In Java I'd use an anonymous inner class. Write the EK9 dynamic class equivalent

Given a Describable trait, create an inline implementation that captures a label variable

Build a one-off trait implementation without defining a named class

Answer:
Create a dynamic class implementing a trait inline:

  myObj <- (label) with trait of Describable as class
    override describe() as pure
      <- rtn as String: label
    default operator ?

(label) captures the local variable. The dynamic class implements the trait's abstract methods -- no named class needed.

See Q1125 for dynamic functions. See Q1129 for trait delegation.

defines module qa.advancedtypes.dynamicclasstrait

  defines trait

    Describable
      describe() as pure abstract
        <- rtn as String?

  defines program

    DynamicClassTraitDemo()
      stdout <- Stdout()
      label <- "Dynamic"

      //Create inline implementation of Describable
      myDescribable <- (label) with trait of Describable as class
        override describe() as pure
          <- rtn as String: label
        default operator ?

      stdout.println(myDescribable.describe())

Java: new Describable() { @Override String describe() { return label; } }. Kotlin: object : Describable { }. EK9: (captures) with trait of X as class.

anonymous capture class dynamic inline trait

dynamic class
inline trait implementation

Explanation: EK9 has no 'new' keyword - create an inline implementation with '(captures) with trait of TraitName as class'. See ek9 -h E01075 for details.


Question: Create a dynamic class with multiple methods implementing a trait inline.

I need an inline class that implements two abstract methods from a trait

In Java I'd use an anonymous class with multiple method overrides. Write the EK9 way

Given a trait with greet() and farewell(), create a one-off inline implementation

Build a dynamic class that overrides multiple trait methods

Answer:
Override multiple abstract methods in a dynamic class:

  obj <- () with trait of Speaker as class
    override greet() as pure
      <- rtn as String: "Hello"
    override farewell() as pure
      <- rtn as String: "Goodbye"
    default operator ?

Every abstract method in the trait must be overridden in the dynamic class body.

See Q1125 for dynamic functions. See Q1126 for dynamic class with capture.

defines module qa.advancedtypes.dynamicclassmethods

  defines trait

    Speaker
      greet() as pure abstract
        <- rtn as String?
      farewell() as pure abstract
        <- rtn as String?

  defines program

    DynamicClassMethodsDemo()
      stdout <- Stdout()

      speaker <- () with trait of Speaker as class
        override greet() as pure
          <- rtn as String: "Hello"
        override farewell() as pure
          <- rtn as String: "Goodbye"
        default operator ?

      stdout.println(speaker.greet())
      stdout.println(speaker.farewell())

Java: anonymous inner class with multiple method overrides. Kotlin: object expression. Python: lambda (single method only). EK9: dynamic class implementing full trait.

class dynamic inline methods multiple trait

multi-method dynamic class
inline implementation

Explanation: EK9 has no 'new' keyword — instantiate a type by calling its constructor directly, e.g. Stdout(). See ek9 -h E01075 for details.


Question: Pass a dynamic class as a function argument.

I need to create an inline trait implementation and pass it to a function

In Java I'd pass an anonymous class to a method. Write the EK9 equivalent

Given a function that takes a Describable, create and pass a dynamic implementation

Build a dynamic class inline at the call site and pass it directly

Answer:
Pass a dynamic class to a function as the trait type:

  myObj <- (label) with trait of Describable as class
    override describe() as pure <- rtn as String: label
    default operator ?
  printDescription(myObj)

The function receives it as Describable -- it does not know or care that it is a dynamic class.

See Q1126 for dynamic class basics. See Q1125 for dynamic functions.

defines module qa.advancedtypes.dynamicclassasargument

  defines trait

    Describable
      describe() as pure abstract
        <- rtn as String?

  defines function

    printDescription()
      -> item as Describable
      <- output as String: item.describe()

  defines program

    DynamicClassAsArgumentDemo()
      stdout <- Stdout()
      label <- "Widget"

      //Create dynamic class implementing Describable
      widget <- (label) with trait of Describable as class
        override describe() as pure
          <- rtn as String: label
        default operator ?

      //Pass it to a function that takes the trait type
      result <- printDescription(widget)
      stdout.println(result)

Java: printDescription(new Describable() { ... }). Kotlin: printDescription(object : Describable { ... }). EK9: create dynamic class, pass as trait type.

argument class dynamic function inline pass

dynamic class as argument
passing inline implementations

Explanation: EK9 has no 'new' keyword; instantiate a type directly as TypeName() (or build a dynamic class first and pass that). See ek9 -h E01075 for details.


Question: Delegate trait methods to another object using the 'by' keyword.

I need a class that forwards all trait method calls to a delegate field

In Kotlin I'd use 'by' delegation. Write the EK9 trait delegation equivalent

Given a Processor trait, create a delegating wrapper that forwards to a real processor

Implement the delegation pattern using 'with trait of X by field'

Answer:
Use 'by fieldName' to delegate all trait methods:

  DelegatingProcessor with trait of Processor by delegate
    delegate as Processor?

All trait methods are forwarded to the delegate field. Composition and delegation replace deep class hierarchies.

See Q1130 for chained delegation. See Q1131 for diamond resolution.

defines module qa.sealedtraits.traitdelegationbasic

  defines trait

    Processor
      process() as pure
        <- result as String: "default"

  defines class

    SimpleProcessor with trait of Processor

      override process() as pure
        <- result as String: "simple"

      default operator ?

    DelegatingProcessor with trait of Processor by delegate
      delegate as Processor?

      default private DelegatingProcessor()

      DelegatingProcessor()
        -> proc as Processor
        require proc?
        delegate := proc

      default operator ?

  defines program

    TraitDelegationBasicDemo()
      stdout <- Stdout()

      simple <- SimpleProcessor()
      delegating <- DelegatingProcessor(simple)

      //Call goes through delegating -> delegate -> simple
      result <- delegating.process()
      stdout.println(`Result: ${result}`)

Kotlin: class Wrapper(p: Processor): Processor by p. Java: manual forwarding methods. Go: embedding. EK9: 'with trait of X by field' — compiler generates forwarding.

by composition delegation forward proxy trait

Explanation: A trait is adopted with 'with trait of', not 'is' (which extends a class); using 'is' on a trait is an incompatible-genus error. See ek9 -h E50020 for details.

Oracle can generate trait delegation using the 'by' keyword with correct method forwarding.


Question: Chain trait delegations so Top delegates to Middle which delegates to Final.

I need a multi-level delegation chain where each layer forwards to the next

In Java I'd chain decorator objects. Write the EK9 chained trait delegation

Given three classes implementing a trait, wire them so calls flow Top -> Middle -> Final

Build a delegation pipeline across multiple levels using 'by' keyword

Answer:
Chain delegators -- each level forwards to the next:

  TopProducer with trait of Producer by delegate
    delegate as Producer?
  MiddleProducer with trait of Producer by delegate
    delegate as Producer?
  FinalProducer with trait of Producer
    override produce() as pure <- result as String: "final"

Calling top.produce() flows: Top -> Middle -> Final.

See Q1129 for basic delegation. See Q1131 for diamond resolution.

defines module qa.sealedtraits.traitdelegationchain

  defines trait

    Producer
      produce() as pure
        <- result as String: "default"

  defines class

    FinalProducer with trait of Producer
      override produce() as pure
        <- result as String: "final"
      default operator ?

    MiddleProducer with trait of Producer by delegate
      delegate as Producer?

      default private MiddleProducer()

      MiddleProducer()
        -> prod as Producer
        require prod?
        delegate := prod

      default operator ?

    TopProducer with trait of Producer by delegate
      delegate as Producer?

      default private TopProducer()

      TopProducer()
        -> prod as Producer
        require prod?
        delegate := prod

      default operator ?

  defines program

    TraitDelegationChainDemo()
      stdout <- Stdout()

      last <- FinalProducer()
      middle <- MiddleProducer(last)
      top <- TopProducer(middle)

      //Call flows: Top -> Middle -> Final
      result <- top.produce()
      stdout.println(`Result: ${result}`)

Java: Decorator pattern with chained wrappers. Python: decorator chain. Go: nested embedding. EK9: chained 'by delegate' fields.

chain delegation forward multi-level pipeline trait

chained delegation
multi-level forwarding

Explanation: Use delegation (by keyword) instead of inheritance for chain-of-responsibility patterns.


Question: Resolve diamond inheritance when a class adopts two traits that share a parent.

I have LeftTrait and RightTrait both extending TopTrait — resolve the conflict

In Java interfaces with diamond inheritance need default method resolution. Show the EK9 way

Given a diamond pattern with conflicting methods, override to resolve them

Handle the case where two traits provide conflicting implementations of the same method

Answer:
Resolve diamond conflicts with explicit override:

  DiamondClass with trait of LeftTrait, RightTrait
    override getShared() as pure
      <- rtn as String: "diamond-shared"

When two traits extend the same parent, conflicting methods must be overridden. Use TraitName.methodName() to call a specific trait's version.

See Q1129 for basic delegation. See Q1132 for explicit trait calls.

defines module qa.sealedtraits.traitdiamond

  defines trait

    TopTrait
      getShared() as pure
        <- mainValue as String: "top-shared"

    LeftTrait is TopTrait
      override getShared() as pure
        <- mainValue as String: "left-shared"

    RightTrait is TopTrait
      override getShared() as pure
        <- mainValue as String: "right-shared"

  defines class

    DiamondClass with trait of LeftTrait, RightTrait

      //Must override to resolve the conflict
      override getShared() as pure
        <- mainValue as String: "diamond-resolved"

      //Explicit access to each trait's version
      getLeftVersion() as pure
        <- mainValue as String: LeftTrait.getShared()

      getRightVersion() as pure
        <- mainValue as String: RightTrait.getShared()

      default operator ?

  defines program

    TraitDiamondDemo()
      stdout <- Stdout()

      diamond <- DiamondClass()
      stdout.println(`Resolved: ${diamond.getShared()}`)
      stdout.println(`Left: ${diamond.getLeftVersion()}`)
      stdout.println(`Right: ${diamond.getRightVersion()}`)

Java: interface default method conflict requires explicit override. C#: explicit interface implementation. EK9: override conflicting methods + TraitName.method() for explicit access.

conflict diamond multiple override resolve trait

diamond inheritance
trait conflict resolution

      getShared() as pure
        <- rtn as String: "resolved"

Explanation: Conflicting trait methods require the 'override' keyword to resolve the ambiguity.


Question: Call a specific trait's method implementation using TraitName.method() syntax.

I need to access a particular trait's version of a method in a class with multiple traits

In Java I'd use InterfaceName.super.method(). Write the EK9 explicit trait call

Given a class with two traits providing getInfo(), call each trait's version explicitly

Disambiguate trait method calls using the TraitName.methodName() syntax

Answer:
Call a specific trait's implementation by name:

  getLeftInfo() as pure
    <- rtn as String: LeftInfo.getInfo()
  getRightInfo() as pure
    <- rtn as String: RightInfo.getInfo()

TraitName.methodName() bypasses override resolution and goes directly to the specified trait.

See Q1131 for diamond resolution. See Q1129 for basic delegation.

defines module qa.sealedtraits.traitexplicitcall

  defines trait

    LeftInfo
      getInfo() as pure
        <- rtn as String: "left-info"

    RightInfo
      getInfo() as pure
        <- rtn as String: "right-info"

  defines class

    Combined with trait of LeftInfo, RightInfo

      //Must override the conflicting method
      override getInfo() as pure
        <- rtn as String: "combined"

      //Explicit calls to each trait's version
      getFromLeft() as pure
        <- rtn as String: LeftInfo.getInfo()

      getFromRight() as pure
        <- rtn as String: RightInfo.getInfo()

      default operator ?

  defines program

    TraitExplicitCallDemo()
      stdout <- Stdout()

      combined <- Combined()
      stdout.println(`Default: ${combined.getInfo()}`)
      stdout.println(`Left: ${combined.getFromLeft()}`)
      stdout.println(`Right: ${combined.getFromRight()}`)

Java: InterfaceName.super.method(). C#: ((IInterface)this).Method(). EK9: TraitName.method() — direct, no casting needed.

TraitName call disambiguate explicit specific trait

explicit trait call
trait method disambiguation

<- rtn as String: ((LeftInfo)this).getInfo()

Explanation: EK9 has no casting. Use TraitName.methodName() to call a specific trait's implementation directly.


Question: Delegate operators through a trait so the delegating class supports $ and ?.

I need a wrapper class that delegates not just methods but also operators via a trait

In Kotlin 'by' delegates interface methods. Show EK9 trait operator delegation

Given a trait with operators, create a delegating class that forwards them

Make a delegating wrapper support $ string and ? isSet through its delegate

Answer:
Trait delegation with 'by' forwards methods AND operators:

  Wrapper with trait of Printable by delegate
    delegate as Printable?

If the trait defines operators (via default operator or explicit), the delegating class forwards them to the delegate.

See Q1129 for basic delegation. See Q1130 for chained delegation.

defines module qa.sealedtraits.traitoperatordelegation

  defines trait

    Printable
      describe() as pure
        <- rtn as String: "default"

  defines class

    RealPrinter with trait of Printable
      override describe() as pure
        <- rtn as String: "RealPrinter"
      default operator ?

    //Delegates all trait members including operators
    PrinterWrapper with trait of Printable by delegate
      delegate as Printable?

      default private PrinterWrapper()

      PrinterWrapper()
        -> printer as Printable
        require printer?
        delegate := printer

      default operator ?

  defines program

    TraitOperatorDelegationDemo()
      stdout <- Stdout()

      real <- RealPrinter()
      wrapper <- PrinterWrapper(real)

      //Delegated method call
      stdout.println(wrapper.describe())

      //Operator ? works through delegation
      stdout.println(`Wrapper set?: ${wrapper?}`)

Kotlin: class Wrapper(p: Printable): Printable by p — delegates methods and properties. EK9: 'with trait of X by field' — delegates methods and operators.

$ ? by delegation forward operator trait

trait operator delegation
operator forwarding

    Wrapper with trait of Printable
      delegate as Printable
      operator $ as pure <- rtn as String: $delegate

Explanation: Use 'by delegate' to automatically forward all trait members including operators. No manual forwarding needed.


Question: Filter positive numbers, double them, and sort the result.

I have a list with negative values and need to keep only positives, transform, then sort

In Java I'd use stream().filter().map().sorted(). Write the EK9 pipeline

Given mixed integers, build a pipeline: filter positives, double each, sort ascending

Chain filter, map, and sort operations in a single stream pipeline

Answer:
Chain pipe-separated stages left to right:
  cat items | filter by isPositive | map by doubleIt | sort > stdout

cat creates the stream, each | adds an operation, > stdout terminates. See Q235, Q1073.

defines module qa.streams.filtermapsort

  defines function

    isPositive() as pure
      -> item as Integer
      <- rtn as Boolean: item > 0

    doubleIt() as pure
      -> item as Integer
      <- rtn as Integer: item * 2

  defines program

    FilterMapSortDemo()
      stdout <- Stdout()

      items <- [3, -1, 4, -5, 2, -3, 1]

      cat items
        | filter by isPositive
        | map by doubleIt
        | sort
        > stdout

Java: stream().filter(x -> x > 0).map(x -> x * 2).sorted(). Python: sorted(x*2 for x in items if x > 0). EK9: cat items | filter by pred | map by fn | sort.

filter map sort pipeline
stream chaining

Explanation: EK9 uses 'cat source | operation | operation > output' syntax, not method chaining.


Question: Sort a list of Item records by price and collect the sorted result.

I have product objects and need to sort them by price using a stream

In Java I'd use stream().sorted(). Write the EK9 record sort pipeline

Given a list of items with names and prices, sort and output them

Build a stream pipeline that sorts custom records by their natural ordering

Answer:
Define 'default operator' on the class, then pipe through sort:
  sorted <- cat items | sort | collect as List of Item

'default operator' generates <=> comparing fields in declaration order. See Q1085, Q1073.

defines module qa.streams.streamrecordpipeline

  defines class

    Item
      name <- String()
      price <- Float()

      Item()
        ->
          name as String
          price as Float
        this.name :=: name
        this.price :=: price

      default operator

  defines program

    StreamRecordPipelineDemo()
      stdout <- Stdout()

      items <- List() of Item
      items += Item("Monitor", 299.99)
      items += Item("Mouse", 19.99)
      items += Item("Keyboard", 49.99)

      //Sort by natural ordering (name first, then price)
      sorted <- cat items | sort | collect as List of Item
      stdout.println("Sorted:")
      cat sorted > stdout

Java: stream().sorted(Comparator.comparing(Item::getPrice)). Python: sorted(items, key=lambda x: x.price). EK9: cat items | sort | collect.

collect order pipeline record sort stream

record sort pipeline
stream sort with records

Explanation: EK9 uses stream pipelines for sorting. Define <=> on the class and use cat | sort.


Question: Collect filtered stream results into a new List.

I need to capture a pipeline's output as a List instead of printing it

In Java I'd use .collect(Collectors.toList()). Write the EK9 equivalent

Given a filtered stream, materialise the results into a List of Integer

Store the output of a stream pipeline in a variable using collect as

Answer:
Use 'collect as' to materialise a stream into a list:
  positives <- cat items | filter by isPositive | collect as List of Integer

The result is a new List containing all items that passed the pipeline. See Q954, Q1134.

defines module qa.streams.streamcollectas

  defines function

    isPositive() as pure
      -> item as Integer
      <- rtn as Boolean: item > 0

  defines program

    StreamCollectAsDemo()
      stdout <- Stdout()

      items <- [10, -5, 20, -3, 30, -1]

      //Collect filtered results into a list
      positives <- cat items
        | filter by isPositive
        | collect as List of Integer

      stdout.println(`Collected ${$ length positives} items`)
      cat positives > stdout

Java: .collect(Collectors.toList()). Python: list(filter(...)). Rust: .collect::<Vec<_>>(). EK9: | collect as List of T.

capture collect list materialise pipeline result


Question: Remove duplicate integers from a list using sort and uniq.

I have a list with repeated values and need to keep only unique items

In Python I'd use set() for dedup. Write the EK9 stream deduplication

Given [3,1,2,1,3,2], produce a sorted list with no duplicates

Deduplicate a list using a sort | uniq pipeline

Answer:
Sort first, then uniq removes consecutive duplicates:
  cat items | sort | uniq > stdout

Sort ensures equal items are adjacent so uniq can remove them. See Q989, Q891.

defines module qa.streams.streamuniqgroup

  defines program

    StreamUniqGroupDemo()
      stdout <- Stdout()

      items <- [3, 1, 2, 1, 3, 2, 1]

      //Sort then uniq to deduplicate
      stdout.println("Sorted unique:")
      cat items | sort | uniq > stdout

      //Sort, group, then flatten
      stdout.println("Sort group flatten:")
      cat items | sort | group | flatten > stdout

Java: stream().distinct().sorted(). Python: sorted(set(items)). Rust: dedup() after sort. EK9: sort | uniq — two-stage pipeline.

deduplicate distinct flatten group sort uniq unique

Explanation: EK9 uses 'uniq' (not 'distinct'). Sort first to ensure equal items are adjacent.


Question: Take the first 3, last 2, and skip the first 2 items from a list.

I need to slice a stream: first N, last N, or drop the first N items

In Python I'd use list[:3], list[-2:], list[2:]. Write the EK9 equivalents

Given [10,20,30,40,50], demonstrate head, tail, and skip operations

Paginate a stream by taking or skipping a fixed number of items

Answer:
head takes first N, tail takes last N, skip drops first N:
  cat items | head 3 > stdout
  cat items | tail 2 > stdout
  cat items | skip 2 > stdout

Combine them: cat items | skip 1 | head 3 > stdout. See Q931.

defines module qa.streams.streamheadtailskip

  defines program

    StreamHeadTailSkipDemo()
      stdout <- Stdout()

      items <- [10, 20, 30, 40, 50]

      stdout.println("Head 3:")
      cat items | head 3 > stdout

      stdout.println("Tail 2:")
      cat items | tail 2 > stdout

      stdout.println("Skip 2:")
      cat items | skip 2 > stdout

      stdout.println("Skip 1 then Head 3:")
      cat items | skip 1 | head 3 > stdout

Java: stream().limit(3), stream().skip(2). Python: list[:3], list[2:]. Rust: .take(3), .skip(2). EK9: | head 3, | skip 2, | tail 2.

first head last paginate skip slice tail take

Explanation: EK9 uses 'head N' not limit(). Similarly 'tail N' and 'skip N'.


Question: Sum a list of integers using join with an addition function.

I need to reduce a stream to a single value by adding all items together

In Java I'd use stream().reduce(). Write the EK9 join equivalent

Given [10, 20, 30], produce the sum using a stream join operation

Aggregate stream items into a single result using join with a binary function

Answer:
join reduces a stream to a single value via a binary function:
  total <- cat [10, 20, 30] | join with addIntegers | collect as Integer

The binary function takes two items and returns one. See Q1137, Q1134.

defines module qa.streams.streamjoinsplit

  defines function

    addIntegers() as pure
      ->
        a as Integer
        b as Integer
      <- rtn as Integer: a + b

    isEven() as pure
      -> item as Integer
      <- rtn as Boolean: item mod 2 == 0

  defines program

    StreamJoinSplitDemo()
      stdout <- Stdout()

      //Join (reduce) to sum
      total <- cat [10, 20, 30] | join with addIntegers | collect as Integer
      stdout.println(`Sum: ${total}`)

      //Split by predicate, then flatten
      stdout.println("Split by even:")
      cat [1, 2, 3, 4, 5, 6]
        | split with isEven
        | flatten
        > stdout

Java: stream().reduce(Integer::sum). Python: functools.reduce(). Rust: .fold(). EK9: | join with fn | collect as T.

aggregate
binary function
join
reduce
split
sum


Question: Capture intermediate sorted results into a side list using tee.

I need to save a snapshot of the stream at a mid-pipeline stage

In Unix I'd use tee to copy output to a file while continuing the pipeline. Show the EK9 tee

Given a sort | head pipeline, capture the sorted items before head truncates them

Tap into a stream pipeline to collect intermediate results without disrupting flow

Answer:
tee copies items to a side list without disrupting the pipeline:
  cat items | sort | tee in sideList | head 3 > stdout

sideList gets all sorted items; the main pipeline continues to head 3. See Q980, Q1138.

defines module qa.streams.streamteecapture

  defines program

    StreamTeeCaptureDemo()
      stdout <- Stdout()

      sideList <- List() of Integer

      //Tee captures sorted items before head truncates
      stdout.println("Pipeline output (head 3):")
      cat [5, 3, 1, 4, 2]
        | sort
        | tee in sideList
        | head 3
        > stdout

      //Side list has ALL sorted items, not just head 3
      stdout.println("Side captured (all sorted):")
      cat sideList > stdout

Unix: cmd | tee file.txt | next. Java: peek() in streams. EK9: | tee in list | continues pipeline.

capture
intermediate
side list
snapshot
tap
tee


Question: Filter a list of fruit names to those longer than 4 characters, then uppercase them.

I have a list of strings and need to keep only long ones and convert to uppercase

In Python I'd use [s.upper() for s in fruits if len(s) > 4]. Write the EK9 pipeline

Given fruit names, filter by length then transform to uppercase using filter | map

Process a list of strings through a multi-stage pipeline with predicate and transform

Answer:
Works with String elements the same as any type:
  cat fruits | filter by isLong | map by toUpper > stdout

Use 'reject by' for the inverse filter: cat fruits | reject by isLong > stdout. See Q1134, Q980.

defines module qa.streams.streamstringpipeline

  defines function

    isLong() as pure
      -> item as String
      <- rtn as Boolean?
      minLength <- 4
      rtn: length item > minLength

    toUpper() as pure
      -> item as String
      <- rtn as String: item.upperCase()

  defines program

    StreamStringPipelineDemo()
      stdout <- Stdout()

      fruits <- ["Banana", "Apple", "Cherry", "Date", "Elderberry"]

      stdout.println("Long fruits uppercased:")
      cat fruits
        | filter by isLong
        | map by toUpper
        > stdout

      stdout.println("Short fruits (rejected by isLong):")
      cat fruits
        | reject by isLong
        > stdout

Java: stream().filter(s -> s.length() > 4).map(String::toUpperCase). Python: list comprehension with filter. EK9: | filter by pred | map by fn.

filter map pipeline reject string uppercase

fruits.stream().filter(s -> s.length() > 4).map(s -> s.toUpperCase())

Explanation: EK9 uses named functions with 'filter by' and 'map by', not lambdas.


Question: Sum the prices of all products over 20 using a stream pipeline.

Write code to filter expensive products and sum their prices in a stream

I have a list of products and need the total price of those costing more than 20

Given a product list, compute the sum of prices above a threshold using a pipeline

In Java I'd use stream().filter().mapToDouble().sum(). Write the EK9 equivalent

Answer:
Filter, map to price, then join with an addition function:
  total <- cat products | filter by isExpensive | map with getPrice | join with addFloats | collect as Float

The join operation reduces a stream to a single value via a binary function. Each pipeline stage uses a named pure function. See Q1139 for join basics. See Q235 for stream operations reference.

defines module qa.streams.sumaggregation

  defines class

    Product
      name as String?
      price as Float?

      default private Product() as pure

      Product() as pure
        ->
          name as String
          price as Float
        this.name :=? name
        this.price :=? price

      name() as pure
        <- rtn as String: String(name)

      price() as pure
        <- rtn as Float: Float(price)

      operator $ as pure
        <- rtn as String: `${name} \$${price}`

      operator #? as pure
        <- rtn as Integer: #?name

      override operator ? as pure
        <- rtn as Boolean: name? and price?

  defines function

    isExpensive() as pure
      -> product as Product
      <- rtn as Boolean?
      expensiveThreshold <- 20.0
      rtn: product.price() > expensiveThreshold

    getPrice() as pure
      -> product as Product
      <- rtn as Float: product.price()

    addFloats() as pure
      ->
        a as Float
        b as Float
      <- rtn as Float: a + b

  defines program

    StreamSumDemo()
      stdout <- Stdout()

      products <- [
        Product("Widget", 15.0),
        Product("Gadget", 45.0),
        Product("Gizmo", 30.0),
        Product("Trinket", 5.0),
        Product("Device", 60.0)
        ]

      // Filter to expensive products, extract price, sum
      total <- cat products | filter by isExpensive | map with getPrice | join with addFloats | collect as Float
      stdout.println(`Total of expensive items: ${total}`)

      // Count expensive items by collecting as list and measuring length
      expensiveList <- cat products | filter by isExpensive | collect as List of Product
      stdout.println(`Number of expensive items: ${length expensiveList}`)

Java: stream().filter(p -> p.price > 20).mapToDouble(Product::getPrice).sum(). Python: sum(p.price for p in products if p.price > 20). Rust: iter().filter().map().sum(). EK9: cat | filter by | map with | join with | collect as.

aggregate filter join map pipeline price reduce stream sum total

total <- products.stream().filter(p -> p.price() > 20).sum()

Explanation: EK9 uses cat/pipe stream syntax, not Java-style .stream() calls. Reduction uses 'join with' and a binary function. See ek9 -h E50060 for details.

      <- rtn as Float?
      rtn: product.price()

Explanation: A function used with 'filter by' must return Boolean; making isExpensive return Float triggers E07520 (must return a Boolean). See ek9 -h E07520 for details.


Question: Take the first 3 positive numbers from a mixed list.

Write code to filter positive numbers and take the first three

I have a list of mixed integers and need only the first 3 positives

Given [-2, 5, -1, 8, 3, -4, 7], produce the first 3 positive values

In Java I'd use stream().filter(n -> n > 0).limit(3). Write the EK9 equivalent

Answer:
Filter with a predicate, then limit with head:
  cat items | filter by isPositive | head 3 > stdout

The head operation takes only the first N items from the stream. Combining filter and head replaces Java's filter().limit() pattern. See Q235 for stream operations. See Q125 for head/tail/skip.

defines module qa.streams.filterhead

  defines function

    isPositive() as pure
      -> num as Integer
      <- rtn as Boolean: num > 0

    intToString() as pure
      -> num as Integer
      <- rtn as String: $num

  defines program

    FilterHeadDemo()
      stdout <- Stdout()

      items <- [-2, 5, -1, 8, 3, -4, 7, 12, -6]

      // Take first 3 positive numbers
      firstThree <- cat items | filter by isPositive | head 3 | collect as List of Integer
      stdout.println(`First 3 positives: ${firstThree}`)

      // Stream directly to stdout
      stdout.println("Streamed:")
      cat items | filter by isPositive | head 3 | map with intToString > stdout

Java: stream().filter(n -> n > 0).limit(3). Python: itertools.islice(filter(...)). Rust: iter().filter().take(3). EK9: cat | filter by | head 3.

filter first head limit pipeline positive stream take

stream head
filter and limit
take first N

Explanation: EK9 uses 'head N' for limiting stream output, not .limit(). See ek9 -h E50060 for details.


Question: Filter a list to items that are both positive and even.

Write code to chain two filter stages in a stream pipeline

I have a list of integers and need only those that are positive AND even

Given a mixed integer list, select values that pass two predicate tests

In Java I'd use stream().filter(n -> n > 0).filter(n -> n % 2 == 0). Write the EK9 equivalent

Answer:
Chain multiple filter stages with the pipe operator:
  cat items | filter by isPositive | filter by isEven | collect as List of Integer

Each filter uses a separate pure predicate function. The pipe operator chains stages naturally, like Unix pipes. See Q235 for stream operations. See Q237 for streams vs loops.

defines module qa.streams.chainfilters

  defines function

    isPositive() as pure
      -> num as Integer
      <- rtn as Boolean: num > 0

    isEven() as pure
      -> num as Integer
      <- rtn as Boolean: num mod 2 == 0

    intToString() as pure
      -> num as Integer
      <- rtn as String: $num

  defines program

    ChainFiltersDemo()
      stdout <- Stdout()

      items <- [-5, 2, -3, 8, 7, -4, 6, 1, 10, -2, 0]

      // Chain two filters: positive AND even
      positiveEvens <- cat items | filter by isPositive | filter by isEven | collect as List of Integer
      stdout.println(`Positive and even: ${positiveEvens}`)

      // Stream directly to stdout
      stdout.println("Streamed:")
      cat items | filter by isPositive | filter by isEven | map with intToString > stdout

Java: stream().filter(pred1).filter(pred2). Python: filter(pred2, filter(pred1, iterable)). Rust: iter().filter().filter(). EK9: cat | filter by pred1 | filter by pred2.

chain even filter multiple pipe pipeline positive predicate stream

chained filters
multiple predicates
stream composition

Explanation: Stream filter predicates must return Boolean. A function used with 'filter by' must return Boolean, not Integer. See ek9 -h E50030 for details.


Question: Print all items from a list directly to stdout using a pipeline.

I need to output every element in a list to the console

In Unix I'd just cat a file. Write the EK9 'cat list to stdout' pattern

Given a list of names, print each one using the > stdout terminal

Stream a list directly to standard output

Answer:
Simplest pipeline -- each item printed on its own line:
  cat names > stdout

Add operations between cat and > stdout as needed. See Q970, Q1134.

defines module qa.streams.pipelinetostdout

  defines program

    PipelineToStdoutDemo()
      stdout <- Stdout()

      names <- ["Alice", "Bob", "Charlie", "Diana"]

      //Direct output
      stdout.println("All names:")
      cat names > stdout

      //Sorted output
      stdout.println("Sorted:")
      cat names | sort > stdout

Unix: cat file. Java: list.forEach(System.out::println). Python: print(*items, sep='\n'). EK9: cat list > stdout.

cat output pipeline print stdout terminal


Question: Assign a value from a function only if it returns a set result, using a guard.

I need to execute a block only when a function returns a meaningful value

In Kotlin I'd use let { } for null-safe access. Write the EK9 guard equivalent

Given a function that might return unset, guard the result before using it

Use an if-guard to safely unwrap an optional result from a function call

Answer:
Guard with <- declares a variable AND checks isSet in one line:

  if userName <- findUser(1)
    stdout.println(`Found: ${userName}`)
  else
    stdout.println("User not found")

  //Same pattern works in switch, for, while, and try:
  while conn <- getConnection()
    process(conn)
  switch record <- database.lookup(id)
    case .type == "USER"
      handleUser(record)

If the right-hand side returns UNSET, the entire block is skipped. The variable only exists inside the guarded block.

See Q1038 for config defaults. See Q1152 for :=? guarded assignment.

defines module qa.controlflow.ifguardassignment

  defines function

    findUser() as pure
      -> userId as Integer
      <- name as String: String()
      if userId == 1
        name: "Alice"

  defines program

    IfGuardAssignmentDemo()
      stdout <- Stdout()

      //Guard: block runs only if findUser returns set
      if userName <- findUser(1)
        stdout.println(`Found: ${userName}`)

      //Guard: unset result skips the block
      if userName2 <- findUser(999)
        stdout.println(`Found: ${userName2}`)
      else
        stdout.println("User not found")

Kotlin: getName()?.let { name -> println(name) }. Swift: if let name = getName(). EK9: if name <- getName().

<- assignment guard if safe unset unwrap


Question: Dispatch on Shape type to produce a description for Circle, Square, and Triangle.

Write code to handle different subtypes using EK9's dispatcher pattern

I have a sealed Shape hierarchy and need type-specific behavior for each shape

Given a Shape that could be Circle, Square, or Triangle, dispatch to the correct handler

In Java I'd use instanceof checks. Write the EK9 dispatcher equivalent

Answer:
Use a dispatcher method on a class with overloads for each type:
  describe() as dispatcher
    -> shape as Shape
    <- rtn as String: "Unknown"
  describe()
    -> shape as Circle
    <- rtn as String: "A circle"

Mark the base method 'as dispatcher'. The compiler generates dispatch logic automatically. No instanceof, no casting, no switch-on-type. This is the ONLY way to do type-based dispatch in EK9. See Q1121 for sealed dispatcher. See Q1122 for dispatcher with fallback.

defines module qa.controlflow.switchontype

  defines trait

    Shape allow only Circle, Square, Triangle
      name() as abstract
        <- rtn as String?

  defines class

    Circle with trait of Shape
      override name()
        <- rtn as String: "Circle"

    Square with trait of Shape
      override name()
        <- rtn as String: "Square"

    Triangle with trait of Shape
      override name()
        <- rtn as String: "Triangle"

    ShapeDescriber

      describe() as dispatcher
        -> shape as Shape
        <- rtn as String: "Unknown shape"

      describe()
        -> shape as Circle
        <- rtn as String: "A circle with curved edges"

      describe()
        -> shape as Square
        <- rtn as String: "A square with four equal sides"

      describe()
        -> shape as Triangle
        <- rtn as String: "A triangle with three sides"

  defines program

    SwitchOnTypeDemo()
      stdout <- Stdout()
      describer <- ShapeDescriber()

      shapes <- List() of Shape
      shapes += Circle()
      shapes += Square()
      shapes += Triangle()

      for shape in shapes
        description <- describer.describe(shape)
        stdout.println(description)

Java: instanceof + cast chain or visitor pattern. Kotlin: sealed class + when(shape) { is Circle -> }. Rust: enum + match. Python: isinstance() checks. EK9: sealed trait + dispatcher — compiler generates dispatch, no casting, no instanceof.

dispatch dispatcher instanceof overload pattern sealed shape trait type

dispatcher pattern
type-based dispatch
switch on type

Explanation: EK9 has no instanceof keyword. Use 'as dispatcher' on a method to dispatch on runtime types. The compiler generates the dispatch logic. See ek9 -h E01010 for details.

switch shape.getClass()
        case Circle
          rtn: "A circle"

Explanation: EK9 has no getClass() method and switch cannot dispatch on types. Use the dispatcher pattern with method overloads for each type. See ek9 -h E50060 for details.


Question: Iterate from 10 down to 1 using a descending for-range.

In Python I'd use range(10, 0, -1). Write the EK9 descending range

Given start=10 and end=1, iterate downward automatically

Loop in reverse order over a numeric range

Answer:
EK9 auto-detects descending when start > end:
  for i in 10 ... 1
    sum: sum + i

No explicit step needed. For custom steps use 'by': for i in 10 ... 1 by 2. See Q1149.

defines module qa.controlflow.forrangedescending

  defines program

    ForRangeDescendingDemo()
      stdout <- Stdout()
      sum <- 0

      //Descending: 10 down to 1 automatically
      for i in 10 ... 1
        sum: sum + i

      //Sum of 10+9+8+...+1 = 55
      stdout.println(`Sum: ${sum}`)

Python: range(10, 0, -1). Java: for(int i=10; i>=1; i--). Go: for i := 10; i >= 1; i--. EK9: for i in 10 ... 1 — automatic descending.

countdown descending for loop range reverse

Explanation: EK9 uses 'for i in start ... end' with three dots. No range() function. Descending is automatic when start > end.


Question: Iterate from 0 to 20 with a step of 5 using for-range with by.

I need a loop that counts in steps of 5 instead of 1

In Python I'd use range(0, 21, 5). Write the EK9 range with step

Given start=0, end=20, step=5, iterate with a custom increment

Loop through a range with a specific step value using 'by'

Answer:
'by' specifies the step value, always positive:
  for i in 0 ... 20 by 5
    stdout.println($i)

EK9 determines direction from start vs end. Descending: for i in 20 ... 0 by 5. See Q1148.

defines module qa.controlflow.forrangewithby

  defines program

    ForRangeWithByDemo()
      stdout <- Stdout()

      //Step by 5
      stdout.println("By 5:")
      for i in 0 ... 20 by 5
        stdout.println($i)

Explanation: EK9 uses 'for i in start ... end by step'. No range() function.


Question: Loop while a connection value remains set, processing each iteration.

Write code to use a while guard that loops while a value is set

I have a supplier that eventually returns unset and need to loop until that happens

Given a function that returns set values for N calls then unset, process each value

In Java I'd use while ((val = getNext()) != null). Write the EK9 guard equivalent

Answer:
Use a while guard with declaration operator:
  while conn <- getConnection() with counter < maxIters
    stdout.println(conn)
    counter++

The guard re-evaluates on EVERY iteration. If getConnection() returns an unset value, the loop terminates cleanly. The 'with' clause adds an additional condition. See Q77 for while guard details. See Q971 for guard expressions.

defines module qa.controlflow.whileguard

  defines class

    ConnectionSupplier
      remaining <- 0

      ConnectionSupplier()
        -> count as Integer
        this.remaining: count

      getConnection()
        <- rtn as String: String()
        if remaining > 0
          rtn: `Connection-${remaining}`
          remaining: remaining - 1

      override operator ? as pure
        <- rtn as Boolean: remaining?

  defines program

    WhileGuardDemo()
      stdout <- Stdout()

      supplier <- ConnectionSupplier(4)
      counter <- 0
      maxIters <- 10

      // Loop while getConnection() returns a SET value
      while conn <- supplier.getConnection() with counter < maxIters
        stdout.println(conn)
        counter: counter + 1

      stdout.println(`Processed ${counter} connections`)

Java: while ((val = getNext()) != null) { process(val); }. Go: for val := getNext(); val != nil; val = getNext(). Rust: while let Some(v) = get_next(). EK9: while val <- getNext() — guard re-evaluates each iteration.

connection declaration guard isset loop poll unset while

while conn <- supplier.getConnection() with true

Explanation: Using a constant Boolean literal (true) as the while-guard's 'with' condition is a pointless expression; supply a real terminating condition instead. See ek9 -h E07390 for details.

Explanation: 'null' does not exist in EK9; use tri-state semantics (unset/set) with the '?' operator and guard expressions instead. See ek9 -h E01073 for details.


Question: Map a day of the week to 'weekday' or 'weekend' using a switch with multiple case values.

I need a switch that groups several values into one case — no fallthrough needed

In Java I'd use switch with fallthrough for grouping. Write the EK9 multi-value case

Given a day name, categorise it using multiple values in a single case line

Handle Monday through Friday in one case and Saturday/Sunday in another

Answer:
Comma-separated values on one case line, no fallthrough by design:
  case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"
    category: "Weekday"
  case "Saturday", "Sunday"
    category: "Weekend"

Multiple case values replace the need for fallthrough entirely. See Q237.

defines module qa.controlflow.switchmultiplecases

  defines program

    SwitchMultipleCasesDemo()
      stdout <- Stdout()

      days <- ["Monday", "Saturday", "Wednesday", "Sunday"]

      for day in days
        category <- "Unknown"
        switch day
          case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"
            category: "Weekday"
          case "Saturday", "Sunday"
            category: "Weekend"
          default
            category: "Unknown"
        stdout.println(`${day}: ${category}`)

Java: case "Mon": case "Tue": (fallthrough). C#: case "Mon": case "Tue": (fallthrough). EK9: case "Monday", "Tuesday" — comma-separated, no fallthrough.

case group multiple switch values weekday weekend

multi-value case
switch without fallthrough

      case "Monday":
      case "Tuesday":
      case "Wednesday":

Explanation: EK9 has no fallthrough and no colons after case. List multiple values with commas on one case line.


Question: Set a default port only if one has not already been provided.

I need to assign a fallback value but only when the variable is unset

In Ruby I'd use ||=. Write the EK9 guarded assignment equivalent

Given an optional port configuration, apply a default if nothing was set

Use :=? to conditionally initialise a variable that might already have a value

Answer:
Only assigns if the target is currently UNSET:
  port :=? 8080

If port is already SET, the assignment is skipped. No if-check needed. See Q1038, Q1091.

defines module qa.controlflow.guardedassignment

  defines program

    GuardedAssignmentDemo()
      stdout <- Stdout()

      //Port is unset — :=? assigns the default
      port <- Integer()
      port :=? 8080
      stdout.println(`Port: ${port}`)

      //Port is already set — :=? is skipped
      port :=? 9090
      stdout.println(`Still: ${port}`)

Ruby: port ||= 8080. Kotlin: port = port ?: 8080. JavaScript: port ??= 8080. EK9: port :=? 8080.

:=? assignment conditional default fallback guarded

:=? guarded assignment
conditional default

      if port == null
        port = 8080

Explanation: EK9 has no null. Use :=? for conditional assignment — it only sets the value if the target is currently unset.


Question: Assign different labels based on a score using if/else.

Write code to categorize a numeric score into grade labels

I have a score and need to assign Excellent, Good, or Needs Work based on thresholds

Given a score from 0-100, produce a text label based on ranges

In Java I'd use if/else if/else to assign a grade. Write the EK9 equivalent

Answer:
Declare variable, assign in each branch:
  label <- "Unknown"
  if score > excellentThreshold
    label: "Excellent"
  else if score > goodThreshold
    label: "Good"
  else
    label: "Needs work"

EK9 has no return. Assign in each branch using the : operator. See Q1146 for if-guard.

defines module qa.controlflow.ifelsevalue

  defines program

    IfElseValueDemo()
      stdout <- Stdout()

      excellentThreshold <- 90
      goodThreshold <- 70

      scores <- [95, 85, 72, 60]

      for score in scores
        label <- "Unknown"
        if score > excellentThreshold
          label: "Excellent"
        else if score > goodThreshold
          label: "Good"
        else
          label: "Needs work"
        stdout.println(`Score ${score}: ${label}`)

Java: if/else if/else with return. Python: if/elif/else. Rust: let label = if { } else { }. EK9: declare variable, then assign in each branch.

assign branch else grade if label score threshold

if score > 90
        return "Excellent"

Explanation: EK9 has no return statement. Declare a variable before the if/else and assign in each branch.


Question: Catch an exception from a division operation and handle it.

I need to handle a runtime error using try/catch in EK9

In Java I'd use try-catch with specific exception types. Write the EK9 equivalent

Given a division that might fail, catch the exception and print an error message

Handle an arithmetic error gracefully using try and catch blocks

Answer:
catch uses -> parameter syntax; ex.reason() gets the message:

  try
    result <- 100 / 5
    stdout.println(`Result: ${result}`)
  catch
    -> ex as Exception
    stdout.println(`Error: ${ex.reason()}`)
  finally
    stdout.println("cleanup")

The catch block declares the exception with -> (data-in port). The finally block always runs. Use ex.reason() not getMessage().

See Q1155 for finally details. See Q1156 for nested try/catch.

defines module qa.controlflow.trycatchbasics

  defines program

    TryCatchBasicsDemo()
      stdout <- Stdout()

      //Safe division
      try
        result <- 100 / 5
        stdout.println(`100 / 5 = ${result}`)
      catch
        -> ex as Exception
        stdout.println(`Error: ${ex.reason()}`)

Java: try { } catch (Exception e) { }. Python: try: except Exception as e:. EK9: try / catch -> ex as Exception.

      catch (Exception ex) {
        System.out.println(ex.getMessage());
      }

Explanation: EK9 uses indentation, not braces. The catch parameter uses -> syntax. Use .reason() not .getMessage().


Question: Run cleanup code after a try block regardless of whether an exception occurred.

I need a finally block that always runs after try/catch

In Java I'd use try-finally for guaranteed cleanup. Write the EK9 equivalent

Given an operation that might fail, ensure cleanup runs either way

Execute teardown logic after both success and failure paths

Answer:
finally always runs after try/catch:
  try
    stdout.println("working")
  catch
    -> ex as Exception
    stdout.println(ex.reason())
  finally
    stdout.println("cleanup")

The finally block executes whether the try succeeds or catch handles an exception.

See Q1154 for basic try/catch.

defines module qa.controlflow.trywithfinally

  defines program

    TryWithFinallyDemo()
      stdout <- Stdout()

      //Success path — finally still runs
      try
        stdout.println("Working")
      catch
        -> ex as Exception
        stdout.println(ex.reason())
      finally
        stdout.println("Cleanup runs regardless")

Java: try { } catch { } finally { }. Python: try/except/finally. Go: defer. EK9: try/catch/finally — same structure as Java.

always cleanup exception finally teardown try

      finally {
        System.out.println("cleanup");
      }

Explanation: EK9 uses indentation, not braces. The finally block is a peer of try and catch.


Question: Catch an exception in an inner try block so the outer catch does not fire.

I need nested error handling where the inner block consumes the exception

In Java nested try-catch handles exceptions at the closest level. Show the EK9 pattern

Given inner and outer try blocks, verify the inner catch prevents outer catch from running

Handle an exception locally in a nested try without propagating to the outer block

Answer:
Inner catch consumes the exception:
  try
    try
      ex <- Exception("inner")
      throw ex
    catch
      -> e as Exception
      stdout.println("Inner handled")
    stdout.println("Outer continues")
  catch
    -> e as Exception
    stdout.println("Outer NOT reached")

Outer catch only fires if the exception is not caught by an inner block.

See Q1154 for basic try/catch. See Q1155 for finally.

defines module qa.controlflow.nestedtrycatch

  defines program

    NestedTryCatchDemo()
      stdout <- Stdout()

      try
        stdout.println("Outer try: start")
        try
          stdout.println("Inner try: about to throw")
          ex <- Exception("Inner exception")
          throw ex
        catch
          -> e as Exception
          stdout.println("Inner catch: handled")
        stdout.println("Outer try: continues after inner block")
      catch
        -> e as Exception
        stdout.println("Outer catch: should not execute")

      stdout.println("Done")

Java: nested try-catch — same semantics. Python: nested try/except. EK9: nested try/catch — inner catch consumes the exception.

catch exception inner nested outer propagate try

Explanation: EK9 has no 'new' keyword. Create the exception first, then throw it: ex <- Exception("msg") / throw ex.


Question: Guard a try block so it only runs when the guard value is set.

I need the try body to execute only if a value is present

In Swift I'd use 'guard let'. Show the EK9 try guard equivalent

Given a possibly-unset value, wrap the try block with a guard assignment

Skip the try body entirely when the guard variable is unset

Answer:
try with guard — body runs only if guard value is set:
  try mainValue <- setValue
    stdout.println(mainValue)
  catch
    -> e as Exception
    stdout.println(e.reason())
  finally
    stdout.println("cleanup")

If setValue is unset, the entire try body is skipped. Finally still runs.

See Q1146 for if-guard. See Q1154 for basic try/catch.

defines module qa.controlflow.tryguardexpression

  defines program

    TryGuardExpressionDemo()
      stdout <- Stdout()

      //Set guard — try body executes
      setValue <- 42
      try mainValue <- setValue
        stdout.println(`Try body: ${mainValue}`)
      catch
        -> e as Exception
        stdout.println(e.reason())
      finally
        stdout.println("Finally: always runs")

      //Unset guard — try body skipped
      unsetValue <- Integer()
      try skipped <- unsetValue
        stdout.println("Should not print")
      catch
        -> e as Exception
        stdout.println("Should not print")
      finally
        stdout.println("Finally on unset guard: still runs")

Swift: guard let value = optional else { return }. Kotlin: value?.let { }. EK9: try value <- expr — guard on the try itself.

Explanation: EK9 has no null literal — 'setValue <- null' is rejected outright; use tri-state semantics (an unset value like Integer()) with the '?' operator instead. See ek9 -h E01073 for details.


Question: Iterate over a Dict and print each key-value pair.

I need to loop through all entries in a dictionary

In Python I'd use for k, v in dict.items(). Write the EK9 Dict iteration

Given a Dict of names to ages, print each entry using for-in

Traverse a Dict and access each key-value pair as a DictEntry

Answer:
for-in iterates over DictEntry objects:
  for entry in ages
    stdout.println($entry)

Each entry displays as key=value. See Q1161 for full Dict operations.

defines module qa.collections.dictiteration

  defines program

    DictIterationDemo()
      stdout <- Stdout()

      ages <- Dict() of (String, Integer)
      ages += DictEntry("Alice", 30)
      ages += DictEntry("Bob", 25)
      ages += DictEntry("Charlie", 35)

      //Print the whole Dict
      stdout.println($ages)

      //Iterate over entries
      for entry in ages
        stdout.println($entry)

Python: for k, v in dict.items(). Java: for (Map.Entry<K,V> e : map.entrySet()). Go: for k, v := range m. EK9: for entry in dict.

Dict entry for-in iterate key-value loop

Explanation: Dict type parameters need parentheses: Dict() of (K, V).


Question: Check if a country code is in a list of approved countries.

Write code to check list membership in EK9

I have a list of valid codes and need to verify a value is in that list

Given a list of approved strings, determine if a candidate is present

In Java I'd use list.contains(). Write the EK9 equivalent

Answer:
Use the contains operator on a List:
  if approved contains countryCode
    stdout.println("Approved")

The 'contains' operator checks whether a value exists in a List or Dict. For List, it checks element membership. For Dict, it checks key existence. See Q45 for List basics. See Q129 for Dict contains.

defines module qa.collections.listcontains

  defines program

    ListContainsDemo()
      stdout <- Stdout()

      approved <- ["GB", "US", "DE", "FR", "JP"]

      // Check membership with contains operator
      countryCode <- "GB"
      if approved contains countryCode
        stdout.println(`${countryCode} is approved`)

      // Check a code that is not in the list
      unknownCode <- "ZZ"
      if not (approved contains unknownCode)
        stdout.println(`${unknownCode} is not approved`)

      // Check multiple codes
      candidates <- ["US", "BR", "FR", "CN"]
      for candidate in candidates
        if approved contains candidate
          stdout.println(`${candidate}: approved`)
        else
          stdout.println(`${candidate}: rejected`)

Java: list.contains(item). Python: item in list. Rust: vec.contains(&item). Go: manual loop (no built-in). JavaScript: array.includes(item). EK9: list contains item — operator syntax, not method call.

approved check collection contains in list lookup membership

list contains
membership check
contains operator

Explanation: 'contains' on a List of String is not defined for an Integer operand — the argument must match the element type. See ek9 -h E07620 for details.


Question: Add, access, and remove items from a List of strings.

I need to perform basic List operations: add, get, remove, check length

In Java I'd use ArrayList methods. Write the EK9 List equivalents

Given a List of names, demonstrate add with +=, access, and length

Show the core List operations on a collection of strings

Answer:
List operations use operators and methods:
  names <- List() of String
  names += "Alice"
  names += "Bob"
  stdout.println($ length names)
  cat names > stdout

+= adds items. 'length' prefix operator returns size. 'cat list > stdout' prints all items.

See Q1158 for Dict iteration. See Q1081 for list merge.

defines module qa.collections.listcomprehensive

  defines program

    ListComprehensiveDemo()
      stdout <- Stdout()

      names <- List() of String
      names += "Alice"
      names += "Bob"
      names += "Charlie"

      //Length
      stdout.println(`Length: ${$ length names}`)

      //Print all items
      cat names > stdout

      //List literal shorthand
      numbers <- [10, 20, 30]
      stdout.println(`Numbers: ${numbers}`)

Java: list.add(), list.size(), list.get(). Python: list.append(), len(list). EK9: += to add, length prefix, cat to iterate.

List access add length operations remove

Explanation: EK9 uses += operator to add items to a list, not .add() method.


Question: Add entries to a Dict, look up a value by key, and iterate over all entries.

I need to build a dictionary, retrieve values, and loop through entries

In Python I'd use dict[key] = value and for k,v in dict.items(). Write the EK9 Dict

Given a Dict of country codes to names, add entries, look up, and iterate

Show the core Dict operations: add with DictEntry, getOrDefault, and for-in

Answer:
Dict operations use DictEntry, getOrDefault, and for-in:
  codes <- Dict() of (String, String)
  codes += DictEntry("GB", "United Kingdom")
  result <- codes.getOrDefault("GB", "Unknown")
  for entry in codes
    stdout.println($entry)

Dict type uses (K, V) parentheses. getOrDefault returns the value or a fallback.

See Q1158 for Dict iteration. See Q1095 for custom Dict keys.

defines module qa.collections.dictcomprehensive

  defines program

    DictComprehensiveDemo()
      stdout <- Stdout()

      codes <- Dict() of (String, String)
      codes += DictEntry("GB", "United Kingdom")
      codes += DictEntry("US", "United States")
      codes += DictEntry("DE", "Germany")

      //Lookup by key
      result <- codes.getOrDefault("GB", "Unknown")
      stdout.println(`GB: ${result}`)

      //Missing key — returns default
      missing <- codes.getOrDefault("FR", "Not found")
      stdout.println(`FR: ${missing}`)

      //Iterate
      for entry in codes
        stdout.println($entry)

Python: dict[key] = value, dict.get(key, default). Java: map.put(), map.getOrDefault(). EK9: += DictEntry(), getOrDefault().

Dict DictEntry add getOrDefault iterate lookup

Explanation: Dict type parameters must be in parentheses: Dict() of (K, V).


Question: Remove all negative numbers from a list, keeping only positives.

Write code to filter out unwanted elements from a list

I have a list of integers and need a new list with only positive values

Given a list with mixed positive and negative numbers, produce a positives-only list

In Java I'd use stream().filter(n -> n > 0).collect(). Write the EK9 equivalent

Answer:
Use a stream pipeline to filter and collect into a new list:
  positives <- cat numbers | filter by isPositive | collect as List of Integer

EK9 does not have a .removeIf() method on lists. Filtering is done through stream pipelines, creating a new collection with only the desired elements. See Q235 for stream operations. See Q122 for collect as.

defines module qa.collections.removematching

  defines function

    isPositive() as pure
      -> num as Integer
      <- rtn as Boolean: num > 0

    intToString() as pure
      -> num as Integer
      <- rtn as String: $num

  defines program

    RemoveMatchingDemo()
      stdout <- Stdout()

      numbers <- [5, -3, 8, -1, 4, -7, 2, -9, 10]
      stdout.println(`Original: ${numbers}`)

      // Filter to keep only positives
      positives <- cat numbers | filter by isPositive | collect as List of Integer
      stdout.println(`Positives only: ${positives}`)

      // Stream filtered results directly
      stdout.println("Streamed positives:")
      cat numbers | filter by isPositive | map with intToString > stdout

Java: list.removeIf(n -> n < 0) or stream().filter().collect(). Python: [n for n in nums if n > 0]. Rust: vec.retain(|n| *n > 0). Go: manual loop. EK9: cat | filter by | collect as — always creates a new list.

collect filter list negative pipeline positive remove stream

filter to new list
remove matching elements
stream collect

Explanation: EK9 lists do not have a removeIf() method. Use a stream pipeline with filter and collect to create a new list with the desired elements. See ek9 -h E50060 for details.


Question: Find the common elements between two lists of names.

Write code to compute the intersection of two lists

I have teamA and teamB lists and need the members in both

Given two lists, filter one to only items that appear in the other

In Python I'd use set(a) & set(b). Write the EK9 list intersection

Answer:
Filter one list by membership in the other:
  common <- cat teamA
    | filter by isInTeamB
    | collect as List of String

Use a dynamic function capturing the second list and checking 'is in'.

See Q1101 for 'is in'. See Q1136 for collect as.

defines module qa.collections.listintersection

  defines function

    InListCheck as pure abstract
      -> name as String
      <- rtn as Boolean?

  defines program

    ListIntersectionDemo()
      stdout <- Stdout()

      teamA <- ["Alice", "Bob", "Charlie", "Diana"]
      teamB <- ["Charlie", "Eve", "Alice", "Frank"]

      //Dynamic function capturing teamB for the membership check
      isInTeamB <- (teamB) extends InListCheck as pure function
        rtn: name is in teamB

      //Filter teamA to only those also in teamB
      common <- cat teamA | filter by isInTeamB | collect as List of String
      stdout.println(`Common members: ${common}`)

Python: set(a) & set(b) or [x for x in a if x in b]. Java: a.stream().filter(b::contains). EK9: cat a | filter by capturedCheck | collect.

both
common
filter
intersection
is in
lists

Explanation: EK9 List has no retainAll() method; compute an intersection with a filter pipeline using 'is in'. See ek9 -h E50060 for details.


Question: Build a formatted string with embedded expressions using backtick interpolation.

I need to embed variable values and arithmetic inside a string

In JavaScript I'd use template literals with ${}. Write the EK9 interpolation

Given name, age, and a calculation, build a formatted output string

Construct a display string with multiple embedded expressions

Answer:
Backtick strings with ${expr} for interpolation:
  stdout.println(`Name: ${name}, Age: ${age}`)
  stdout.println(`Total: ${price * quantity}`)

$ inside backticks is the interpolation marker, not the $ string operator. See Q909, Q918.

defines module qa.operators.interpolationpatterns

  defines program

    InterpolationPatternsDemo()
      stdout <- Stdout()

      name <- "Alice"
      age <- 30
      price <- 9.99
      quantity <- 3

      //Basic interpolation
      stdout.println(`Name: ${name}, Age: ${age}`)

      //Arithmetic inside ${}
      stdout.println(`Total: ${price * quantity}`)

      //Multiple expressions
      stdout.println(`${name} is ${age} years old`)

JavaScript: `Hello ${name}`. Kotlin: "Hello $name". Python: f"Hello {name}". EK9: `Hello ${name}` — same as JavaScript.

backtick embed format interpolation string template

stdout.println("Name is " + name + " today")

Explanation: EK9 forbids 3+ part string concatenation with '+'; use backtick interpolation instead. See ek9 -h E11068 for details.


Question: Split a comma-separated string into a list of fields.

Write code to split a CSV line by commas into separate fields

I have a comma-delimited string and need each field as a list element

Given "Alice,Bob,Charlie", produce a list ["Alice", "Bob", "Charlie"]

In Java I'd use str.split(","). Write the EK9 equivalent

Answer:
Use the split method with a RegEx parameter:
  fields <- line.split(/,/)

The split() method takes a RegEx and returns a List of String. You can then stream the result with cat or access individual elements. See Q33 for regular expressions. See Q175 for string transform patterns.

defines module qa.operators.splitstring

  defines program

    SplitStringDemo()
      stdout <- Stdout()

      // Split a CSV line by comma
      csvLine <- "Alice,Bob,Charlie,Diana"
      fields <- csvLine.split(/,/)
      stdout.println(`Fields: ${fields}`)

      // Stream the split results
      stdout.println("Individual fields:")
      cat fields > stdout

      // Split with more complex regex (whitespace)
      sentence <- "Hello   World   EK9"
      words <- sentence.split(/ +/)
      stdout.println(`Words: ${words}`)

      // Split and count
      fieldCount <- length fields
      stdout.println(`Number of fields: ${fieldCount}`)

Java: str.split(",") returns String[]. Python: str.split(",") returns list. Rust: str.split(',').collect(). Go: strings.Split(str, ","). EK9: str.split(/,/) takes RegEx, returns List of String.

comma csv delimiter fields list parse regex split string

Explanation: split() takes a RegEx (delimited by '/'), not a String - use /,/ not ",". See ek9 -h E50060 for details.


Question: Extract the first and last characters from a string.

Write code to get the prefix and suffix characters of a string

I have a string and need its first character and last character separately

Given a name string, extract the initial and final characters using operators

In Java I'd use charAt(0) and charAt(length-1). Write the EK9 equivalent

Answer:
Use the prefix (#<) and suffix (#>) operators:
  firstChar <- #< name
  lastChar <- #> name

The #< operator returns the first character (as a Character) and #> returns the last character. These are introspection operators available on String. See Q242 for conversion and introspection operators. See Q238 for the complete operator set.

defines module qa.operators.substringextract

  defines program

    SubstringExtractDemo()
      stdout <- Stdout()

      name <- "Hello"

      // Extract first and last characters
      firstChar <- #< name
      lastChar <- #> name
      stdout.println(`First: ${firstChar}`)
      stdout.println(`Last: ${lastChar}`)

      // Use with different strings
      words <- ["EK9", "World", "A"]
      for word in words
        first <- #< word
        last <- #> word
        stdout.println(`'${word}' -> first: ${first}, last: ${last}`)

      // Length for context
      size <- length name
      stdout.println(`Length of '${name}': ${size}`)

Java: str.charAt(0) and str.charAt(str.length()-1). Python: str[0] and str[-1]. Rust: str.chars().next() and str.chars().last(). Go: str[0] and str[len(str)-1]. EK9: #< str and #> str — prefix and suffix operators.

character extract first introspection last operator prefix string suffix

prefix operator
suffix operator
character extraction

Explanation: String has no charAt() method. Use the #< prefix operator to get the first character and #> suffix operator for the last character. See ek9 -h E50060 for details.


Question: Write a function that returns a set or unset String depending on input.

I need a function that sometimes returns a value and sometimes returns nothing

In Java I'd return Optional<String>. Write the EK9 function with optional return

Given a lookup function, return the found value or leave the return unset

Create a function whose return can be checked with ? by the caller

Answer:
String() creates an unset return; caller guards with ?:
  <- colour as String: String()
  if name == "sky"
    colour: "blue"

If the condition doesn't match, the return stays unset. Caller uses if-guard: if found <- findColour("sky"). See Q1146, Q1087.

defines module qa.functionsandmethods.functionoptionalreturn

  defines function

    findColour() as pure
      -> name as String
      <- colour as String: String()
      if name == "sky"
        colour: "blue"
      else if name == "grass"
        colour: "green"

  defines program

    FunctionOptionalReturnDemo()
      stdout <- Stdout()

      //Found — guard executes block
      if skyColour <- findColour("sky")
        stdout.println(`Sky: ${skyColour}`)

      //Not found — guard skips block
      if oceanColour <- findColour("ocean")
        stdout.println(`Ocean: ${oceanColour}`)
      else
        stdout.println("Ocean colour not found")

Java: Optional<String>. Kotlin: String?. Rust: Option<String>. EK9: return String() (unset) or a value — caller uses ? or guard.

function guard lookup optional return unset

optional return
function with unset return

Explanation: EK9 doesn't use Optional for function returns. Return an unset value (String()) and let the caller guard with ?.


Question: Write a pure validation function that checks if an age is between 0 and 150.

Write code to validate a numeric range using a pure function

I have an age value and need to verify it falls within a valid range

Given an integer, produce a Boolean indicating whether it is a valid age

In Java I'd write a static boolean isValidAge(int age). Write the EK9 equivalent

Answer:
Define a pure function with a Boolean return:
  isValidAge() as pure
    -> age as Integer
    <- rtn as Boolean: age >= 0 and age <= 150

Pure functions cannot modify parameters or access external state. They are ideal for validation logic because they are testable, composable, and safe to use in stream pipelines. See Q596 for function vs method. See Q568 for pure basics.

defines module qa.functionsandmethods.validation

  defines function

    isValidAge() as pure
      -> age as Integer
      <- rtn as Boolean?
      maxAge <- 150
      rtn: age >= 0 and age <= maxAge

    isValidPercentage() as pure
      -> pct as Integer
      <- rtn as Boolean?
      maxPercent <- 100
      rtn: pct >= 0 and pct <= maxPercent

    isNonBlank() as pure
      -> text as String
      <- rtn as Boolean: text? and text.length() > 0

  defines program

    ValidationDemo()
      stdout <- Stdout()

      // Validate ages
      ages <- [25, -1, 0, 150, 151, 42]
      for age in ages
        if isValidAge(age)
          stdout.println(`Age ${age}: valid`)
        else
          stdout.println(`Age ${age}: invalid`)

      // Validate percentages
      scores <- [0, 50, 100, 101, -5]
      for score in scores
        if isValidPercentage(score)
          stdout.println(`Score ${score}: valid`)
        else
          stdout.println(`Score ${score}: invalid`)

      // Validate strings
      names <- ["Alice", "", "Bob"]
      for name in names
        if isNonBlank(name)
          stdout.println(`Name '${name}': valid`)
        else
          stdout.println(`Name '${name}': blank`)

Java: static boolean isValidAge(int age) { return age >= 0 && age <= 150; }. Python: def is_valid_age(age): return 0 <= age <= 150. Rust: fn is_valid_age(age: i32) -> bool. EK9: isValidAge() as pure -> age as Integer <- rtn as Boolean.

age boolean check function predicate pure range validation

pure validation function
range check
predicate function

Explanation: EK9 has no return statement; assign the result to the declared return variable instead. See ek9 -h E01072 for details.


Question: Apply two transformations in sequence: double a number then add ten.

Write code to chain two map stages in a stream pipeline

I have a list of integers and need to apply two sequential transformations

Given [1, 2, 3], double each value then add ten to each result

In Java I'd use stream().map(x -> x * 2).map(x -> x + 10). Write the EK9 equivalent

Answer:
Chain map stages with separate pure functions:
  cat items | map with doubleIt | map with addTen | collect as List of Integer

Each map stage applies a pure function that transforms one value to another. Chaining multiple map stages composes transformations naturally through the pipeline. See Q235 for stream operations. See Q596 for function basics.

defines module qa.functionsandmethods.composefunctions

  defines function

    doubleIt() as pure
      -> num as Integer
      <- rtn as Integer: num * 2

    addTen() as pure
      -> num as Integer
      <- rtn as Integer: num + 10

    intToString() as pure
      -> num as Integer
      <- rtn as String: $num

  defines program

    ComposeFunctionsDemo()
      stdout <- Stdout()

      items <- [1, 2, 3, 4, 5]

      // Chain two transformations: double then add ten
      transformed <- cat items | map with doubleIt | map with addTen | collect as List of Integer
      stdout.println(`Doubled then plus ten: ${transformed}`)

      // Stream to stdout
      stdout.println("Streamed:")
      cat items | map with doubleIt | map with addTen | map with intToString > stdout

Java: stream().map(x -> x * 2).map(x -> x + 10). Python: map(lambda x: x + 10, map(lambda x: x * 2, items)). Rust: iter().map(|x| x * 2).map(|x| x + 10). EK9: cat | map with fn1 | map with fn2.

chain compose function map pipeline sequence stream transform

function composition
chained map
stream transformation

Explanation: EK9 streams use 'cat ... | map with fn | collect as ...' pipe syntax, not Java-style '.stream().map().collect()' method chains. See ek9 -h E50060 for details.


Question: Use an enumeration value in a switch statement to select behaviour.

I need to switch on an enum value and handle each case

In Java I'd use switch on an enum. Write the EK9 enum switch pattern

Given a Priority enum, map each value to a label using switch

Dispatch on enumeration values using switch with case

Answer:
Qualify enum values with the type name in switch cases:
  switch priority
    case Priority.HIGH
      label: "Urgent"
    case Priority.MEDIUM
      label: "Normal"

No fallthrough -- each case is independent. See Q1151.

defines module qa.enumerations.enumguard

  defines type

    Priority
      HIGH
      MEDIUM
      LOW

  defines program

    EnumGuardDemo()
      stdout <- Stdout()

      priorities <- [Priority.HIGH, Priority.MEDIUM, Priority.LOW]

      for priority in priorities
        label <- "Unknown"
        switch priority
          case Priority.HIGH
            label: "Urgent"
          case Priority.MEDIUM
            label: "Normal"
          case Priority.LOW
            label: "Can wait"
          default
            label: "Unknown"
        stdout.println(`${priority}: ${label}`)

Java: switch(priority) { case HIGH: ... }. Kotlin: when(priority) { HIGH -> ... }. EK9: switch priority / case Priority.HIGH.

case dispatch enum enumeration switch value

Explanation: EK9 enums must be qualified with the type name: Priority.HIGH, not just HIGH.