Why doesn't EK9 have switch fallthrough and how do I group cases?

← Control Flow · Ref: Q147

Switch fallthrough is one of the most dangerous features in programming. EK9 eliminates it entirely and provides a safer, clearer alternative.

THE FALLTHROUGH PROBLEM

In C, Java, and JavaScript, switch cases fall through to the next case by default. Forgetting a break statement causes silent execution of unintended code. CERT ranks this as the 7th most dangerous coding error. The bug is insidious because the code compiles and often appears to work until an edge case triggers the missing break.

A CLASSIC FALLTHROUGH BUG

In Java, this code silently assigns the wrong category:

  switch (code) {
    case 1: result = "admin";
    // missing break - falls through!
    case 2: result = "user";
    break;
  }

When code is 1, result becomes "user" instead of "admin". The compiler gives no warning. This pattern has caused countless production bugs.

EK9 SOLUTION: MULTIPLE VALUES PER CASE

EK9 uses comma-separated values in a single case clause:

  switch code
    case 1, 2, 3
      category: "low"
    case 4, 5
      category: "high"
    default
      category: "unknown"

Each case runs its body and stops. There is no fallthrough mechanism in the language.

SWITCH AS EXPRESSION

Switch can return a value directly:

  label <- switch priority
    <- rtn as String?
    case 1, 2
      rtn: "Low"
    case 3
      rtn: "Medium"
    case 4, 5
      rtn: "High"
    default
      rtn: "Unknown"

COMPARISON OPERATORS IN CASES

Cases can use comparison operators for range matching:

  switch score
    case >= 90
      grade: "A"
    case >= 80
      grade: "B"
    case >= 70
      grade: "C"
    default
      grade: "F"

ENUM EXHAUSTIVENESS

With enumerations, the compiler can verify all values are handled:

  switch colour
    case Colour.Red
      label: "stop"
    case Colour.Amber
      label: "caution"
    case Colour.Green
      label: "go"

See Q63 for basic switch syntax. See Q68 for switch as expression. See Q69 for multiple case values. See Q70 for comparison operators in cases. See Q73 for enum exhaustiveness. See Q144 for the full control flow philosophy.

Example

defines module qa.flow.philosophy.nofallthrough

  defines type
    Colour
      Red
      Amber
      Green

  defines program

    NoFallthroughDemo()
      stdout <- Stdout()

      // === MULTIPLE VALUES PER CASE ===

      codes <- [1, 2, 3, 4, 5, 6]
      for code in codes
        category <- String()
        switch code
          case 1, 2, 3
            category: "low"
          case 4, 5
            category: "high"
          default
            category: "unknown"
        stdout.println(`Code ${code} -> ${category}`)

      // === SWITCH AS EXPRESSION ===

      priorities <- [1, 3, 5]
      for priority in priorities
        label <- switch priority
          <- rtn as String?
          case 1, 2
            rtn: "Low"
          case 3
            rtn: "Medium"
          case 4, 5
            rtn: "High"
          default
            rtn: "Unknown"
        stdout.println(`Priority ${priority}: ${label}`)

      // === COMPARISON OPERATORS IN CASES ===

      scores <- [95, 82, 71, 55]
      for score in scores
        grade <- String()
        switch score
          case >= 90
            grade: "A"
          case >= 80
            grade: "B"
          case >= 70
            grade: "C"
          default
            grade: "F"
        stdout.println(`Score ${score}: grade ${grade}`)

      // === ENUM SWITCH ===

      colours <- [Colour.Red, Colour.Amber, Colour.Green]
      for colour in colours
        meaning <- String()
        switch colour
          case Colour.Red
            meaning: "stop"
          case Colour.Amber
            meaning: "caution"
          case Colour.Green
            meaning: "go"
          default
            meaning: "unknown"
        stdout.println(`${colour} means ${meaning}`)

Common mistakes

E01070 — EK9 has no break statement. Each case clause is self-contained with no fallthrough. The break keyword does not exist in the language. See ek9 -h E01070 for details.

Incorrect:

case 1, 2, 3
            category: "low"
            break

Correct:

case 1, 2, 3
            category: "low"

E01072 — EK9 has no return statement. Switch expressions automatically return the declared variable's value. There is no need (and no way) to explicitly return from a program. See ek9 -h E01072 for details.

Incorrect:

return label

Correct:

stdout.println(`Priority ${priority}: ${label}`)

E07320 — Non-enum switch statements require a default clause to handle unexpected values. Without it, the compiler reports E07320. This ensures every possible value is handled. Enum switches with all values covered do not need default. See ek9 -h E07320 for details.

Incorrect:

//no default case

Correct:

default
            category: "unknown"
Other ways to ask this
  • How does EK9 prevent switch fallthrough bugs?
  • What is wrong with switch fallthrough in other languages?
  • How do I handle multiple values in one case without fallthrough in EK9?
  • How do comma-separated case values replace switch fallthrough in EK9?

Coming from another language?

Java: switch fallthrough by default, break required to prevent it, switch expressions with arrow syntax since Java 14 eliminate fallthrough. C/C++: switch fallthrough by default, break required, Clang and GCC warn but cannot prevent. JavaScript: switch fallthrough by default, break required. Python: match/case since 3.10 with no fallthrough, pipe operator for multiple values. Rust: match with no fallthrough, pipe operator for multiple patterns, exhaustive. Go: switch with no fallthrough by default (opposite of C), explicit fallthrough keyword if needed. Kotlin: when with no fallthrough, comma-separated values. Swift: switch with no fallthrough, comma-separated values, exhaustive. C#: switch with no fallthrough between non-empty cases. EK9: no fallthrough mechanism exists, comma-separated case values, comparison operators in cases, switch as expression, enum exhaustiveness.

Keywords: fallthrough, multiple, comma, migrate, flow, branch, break, expression, condition, danger, silent, values, case, safety, switch, control, exhaustive, cert, bug