Create me a two-parameter dispatcher Combiner with handlers for (Circle, Circle) and (Circle, Rectangle), demonstrating that parameter order matters and unmatched combinations fall back to the entry method.

← Dispatcher Validation · Ref: Q1245

EK9 dispatchers can resolve on multiple parameter types at once. With two parameters, the dispatcher matches on the runtime type of EACH parameter independently, so handler selection considers the full combination, not just the first parameter.

SHAPE HIERARCHY

  Shape as abstract
    default operator ?
  Circle is Shape
    default operator ?
  Rectangle is Shape
    default operator ?

TWO-PARAMETER DISPATCHER

  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"

The entry method takes both parameters as the parent type Shape. Each handler narrows BOTH parameters to specific subtypes.

DISPATCH BEHAVIOUR

  combiner.combine(circle, circle)        // "Circle-Circle" — exact match
  combiner.combine(circle, rectangle)     // "Circle-Rectangle" — exact match
  combiner.combine(rectangle, circle)     // "Generic" — no (Rectangle, Circle) handler
  combiner.combine(rectangle, rectangle)  // "Generic" — no handler for this pair

KEY INSIGHT

Parameter ORDER matters: (Circle, Rectangle) and (Rectangle, Circle) are DIFFERENT dispatch keys. If you want them to behave the same, you must declare both handlers. Unhandled combinations fall through to the entry method's body, which acts as the default.

This is true multiple dispatch — found in CLOS, Julia, Common Lisp — but rare in mainstream languages. Java/C# require visitor or instanceof chains; EK9 makes it a one-liner per case.

See Q619 for two-parameter dispatch basics. See Q620 for hierarchy rules. See Q1244 for deep hierarchy single-parameter dispatch.

Example

defines module qa.dispatcher.twoparam

  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

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

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

      stdout.println(combiner.combine(circle, circle))
      stdout.println(combiner.combine(circle, rectangle))
      stdout.println(combiner.combine(rectangle, circle))
      stdout.println(combiner.combine(rectangle, rectangle))

Common mistakes

E01082 — Multiple parameters are declared with a single '->' followed by an indented parameter block. Repeating '->' for each parameter is a parser-level syntax error. See ek9 -h E01082 for details.

Incorrect:

combine() as dispatcher
        -> s1 as Shape
        -> s2 as Shape

Correct:

combine() as dispatcher
        ->
          s1 as Shape
          s2 as Shape
Other ways to ask this
  • Show me a dispatcher that resolves on TWO parameter types simultaneously.
  • Implement a combine method that dispatches differently for different shape pairs.
  • Build a multi-method-style dispatcher with two parameters in EK9.
  • Write a dispatcher demonstrating asymmetric handler coverage on parameter pairs.

Coming from another language?

Java: nested instanceof or double-dispatch via visitor. Scala: pattern match on tuple (s1, s2) match { case (Circle, Circle) => ... }. Common Lisp / CLOS: defmethod with two specialised parameters — the inspiration. Julia: multimethod with type ascriptions on each parameter. EK9: native two-parameter dispatcher with cost-based selection on both arguments.

Keywords: dispatcher, two parameter, parameter order, fallback, asymmetric, combine, multiple dispatch