Design Overview¶
Patternia treats pattern matching as an expression over a concrete subject:
match(subject) | on(
case_1,
case_2,
_ >> fallback
)
The library is built around four ideas:
- Subject flow is explicit.
- Binding is explicit.
- Cases are ordered and first-match-wins.
- The public syntax stays small.
Subject-First Matching¶
Patternia does not hide the matched value inside an implicit control-flow form. You always start with the subject:
match(x) | on(
lit(1) >> "one",
_ >> "other"
);
This makes the match expression read as data flow rather than as a block-level statement form.
Immediate Evaluation¶
match(subject) by itself is only the left side of the pipeline.
Evaluation happens when the on(...) case pack is supplied:
auto result = match(x) | on(
lit(0) >> 0,
lit(1) >> 1,
_ >> -1
);
There is no separate chained builder API.
Explicit Binding¶
Matching and binding are deliberately separate. Patterns answer "does this match?" Binding answers "what values are exposed to the handler?"
match(x) | on(
$ >> [](int v) { return v; },
_ >> 0
);
match(p) | on(
$(has<&Point::x, &Point::y>) >> [](int x, int y) {
return x + y;
},
_ >> 0
);
This separation keeps handler signatures predictable and keeps data flow local.
Guards Refine a Bound Case¶
Guards apply after a binding pattern succeeds.
match(x) | on(
$[PTN_LET(value, value > 0 && value < 10)] >> "small",
_ >> "other"
);
The evaluation model is:
- Match the pattern.
- Bind values.
- Evaluate the guard.
- Run the handler on success.
If the guard fails, matching continues with the next case.
Wildcard Fallback¶
Patternia requires an explicit fallback case in on(...).
match(v) | on(
is<int> >> "int",
is<std::string> >> "string",
_ >> "other"
);
This keeps the terminal behavior visible inside the case list itself.
Structural and Variant Matching Share One Core¶
Literal matching, structural matching, guarded binding, and variant dispatch all lower through the same ordered case model.
match(value) | on(
lit(1) >> "literal",
$(has<&Point::x, &Point::y>) >> [](int x, int y) {
return x + y > 0 ? "point" : "origin-side";
},
$(is<std::string>)[PTN_LET(text, text != "")] >> "string",
_ >> "other"
);
That shared model is what keeps the DSL small without giving up expressive power.
Performance Direction¶
Patternia aims at zero-overhead abstractions:
- no virtual dispatch
- no RTTI
- no heap allocation
- aggressive inlining and compile-time validation
For repeated hot paths, users can cache case packs with static_on(...) or
PTN_ON(...).
Summary¶
Patternia is intentionally narrow:
- one subject-first entry
- one case-pack terminal form
- explicit binding
- explicit wildcard fallback
That constraint is part of the design.