functional-reactive
Made in the European Union

Case

Declarative branching without switch fall-through.

Case lets you express conditional logic as data: each branch is a pair of condition and result, evaluated in order. Unlike switch, there is no fall-through; unlike if/else, every branch must yield a Result<T>.

API at a glance

Case exposes three static methods:

  • Case.matchCase(Supplier<Boolean> condition, Supplier<Result<T>> value) โ€” builds one branch.
  • Case.matchCase(Supplier<Result<T>> value) โ€” builds the default branch (a DefaultCase<T>).
  • Case.match(DefaultCase<T> defaultCase, Case<T>... matchers) โ€” evaluates the branches and returns the first matching Result<T>. Falls back to the default if none match.

Basic usage

import static com.svenruppert.functional.matcher.Case.match;
import static com.svenruppert.functional.matcher.Case.matchCase;
import static com.svenruppert.functional.model.Result.success;
import static com.svenruppert.functional.model.Result.failure;

int score = 87;

Result<String> grade = match(
    matchCase(()             -> success("F")),               // default
    matchCase(() -> score >= 90, () -> success("A")),
    matchCase(() -> score >= 80, () -> success("B")),
    matchCase(() -> score >= 70, () -> success("C"))
);

grade.ifPresentOrElse(
    System.out::println,                                     // "B"
    err -> System.err.println("no match: " + err)
);

Both the condition and the value are wrapped in Suppliers โ€” they are evaluated lazily, in the order they appear, and only until the first match.

Functions as results

Because each branch returns a Result<T>, T can be anything โ€” including a Function. That lets you assemble computation pipelines based on input:

Result<Function<Integer, Integer>> op = match(
    matchCase(()             -> success(v -> v)),            // identity
    matchCase(() -> x == 1, () -> success(v -> v + 1)),
    matchCase(() -> x == 2, () -> success(v -> v + 2)),
    matchCase(() -> x  > 2, () -> success(v -> v + 3))
);

op.map(f -> f.apply(10))
  .ifPresent(System.out::println);

When to reach for Case

Case vs switch vs if/else
Use Case when branch order matters and each branch needs to produce a value declaratively. Stick with switch for cheap enum/int dispatch, and with if/else when you don’t need a result.