The Problem with Chasing Control Flow

In 2024, developer Kentaro Morishita embarked on a mission to streamline code, specifically targeting the ubiquitous if statement. His initial goal, articulated in a Qiita article titled "The Plan to Eradicate if Statements," wasn't a literal eradication but a deeper exploration into how conditional logic could be expressed more clearly. Morishita found himself wrestling with complex if-else structures, not because the logic itself was intricate, but because the act of tracing the control flow obscured the core intent: distinguishing between different cases.

The frustration was particularly acute in TypeScript. While the language supports standard conditional statements, Morishita felt that for certain scenarios, the verbosity of if statements made the code harder to read and maintain. He illustrated this with an example involving a score variable, where a series of if and else if conditions were used to assign a label. This pattern, he argued, forces the developer to mentally parse each condition sequentially, rather than focusing on the distinct outcomes each condition represents.

Morishita realized that his true objective was not to eliminate decision-making in code, but to make the *expression* of those decisions more direct and readable. When faced with multiple, distinct conditions that lead to different outcomes, the traditional if-else chain can become a tangled web. Each new condition requires adding another branch, potentially increasing nesting and making it harder to see the complete picture at a glance. This approach is akin to navigating a maze when you simply want to reach one of several distinct rooms.

TypeScript code snippet demonstrating a complex if-else if chain for score-based labeling.

Introducing 'match': A More Expressive Alternative

The search for a cleaner syntax led Morishita to consider pattern matching, a feature common in functional programming languages. Pattern matching allows developers to define different cases based on the structure or value of an input, and execute specific code for each case. This is precisely what Morishita needed: a way to express the distinct outcomes without the overhead of sequential conditional checks.

He decided to integrate a match statement into his own language. The match statement operates differently from if. Instead of evaluating a series of boolean conditions, it takes an expression and compares its value against a series of patterns. When a pattern matches, the corresponding code block is executed, and the evaluation stops. This provides a more declarative way to handle multiple, discrete cases. For instance, if the input is a specific string, a particular branch executes; if it's another string, a different branch runs. It’s like having a well-organized filing cabinet where each file is clearly labeled, and you go directly to the correct one, rather than sifting through a pile of unsorted papers.

Morishita's experience highlighted a fundamental difference in intent. if statements are primarily for controlling program flow based on boolean conditions. They are excellent for branching based on ranges, complex logical combinations, or status flags. However, when the goal is to simply select one of several distinct actions or values based on a single input, match offers superior clarity. It emphasizes the *what* (the specific case being handled) rather than the *how* (the sequence of checks to arrive at that case).

The 'match' Statement in Practice

Consider a scenario where a program needs to process different types of user input. With if-else, this might look like:

if (inputType === "text") {
  handleTextInput();
} else if (inputType === "number") {
  handleNumberInput();
} else if (inputType === "boolean") {
  handleBooleanInput();
} else {
  handleUnknownInput();
}

The match equivalent, conceptually, would be:

match (inputType) {
  case "text": handleTextInput(); break;
  case "number": handleNumberInput(); break;
  case "boolean": handleBooleanInput(); break;
  default: handleUnknownInput();
}

While this example uses switch/case syntax, common in many languages, the underlying principle is pattern matching. Morishita's custom language implementation likely offers a more robust and expressive form of this, potentially allowing for destructuring, type checking, and more complex pattern matching within the match construct itself.

The benefit is immediate: the code reads as a declaration of intent. "When the input is 'text', do this. When it's 'number', do that." This is far more direct than "If the input is not 'text' and not 'number' and not 'boolean', then check if it's 'text'. If not, check if it's 'number'. If not, check if it's 'boolean'. If none of those, do this other thing." The latter is a procedural description of how to find the right path; the former is a declarative statement of the paths themselves.

Beyond Simple Conditionals

Morishita's work isn't just about replacing if with match for the sake of it. It's about recognizing that different language constructs serve different purposes. if statements excel at evaluating boolean expressions and controlling program flow based on conditions that might involve ranges, logical operators (AND, OR, NOT), or complex state checks. They are fundamental for implementing algorithms that rely on iterative refinement or dynamic decision-making.

However, when the problem domain consists of distinct, discrete states or types, pattern matching with a match statement offers significant advantages in terms of readability, maintainability, and reduced cognitive load. It helps prevent bugs that arise from missed cases or incorrect conditional logic in long if-else chains. By explicitly defining each case, developers are encouraged to consider all possibilities, leading to more robust code.

The surprise here is not that alternatives to if exist, but that the drive to eliminate if led not to its removal, but to the integration of a construct that, in many ways, is a more specialized and powerful tool for a specific class of problems. It’s like realizing you don’t need to break down a wall to get to the next room; you just need a door. And sometimes, a `match` statement is that door.

What remains to be seen is how widely this pattern-matching approach will be adopted in mainstream languages and development practices. As developers increasingly encounter complex data structures and state management challenges, the clarity offered by constructs like match will likely become more appealing, potentially pushing the evolution of conditional logic syntax in popular programming languages.