Skip to content

Releases: sentomk/patternia

v0.9.0

13 Mar 13:25

Choose a tag to compare

Patternia v0.9.0

Patternia v0.9.0 is an API modernization and compiler compatibility release. It introduces PTN_WHERE and PTN_LET as named guard macros, removes the legacy bind() entry point and positional guard aliases, fixes callable guard evaluation on MSVC, and adds vcpkg packaging support.

Highlights

  • Added PTN_WHERE((names...), expr) for naming guard arguments without writing a lambda (supports 1 to 5 bound values).
  • Added PTN_LET(name, expr) as single-value shorthand for PTN_WHERE((name), expr).
  • Added is<T>, as<T>, alt<I> variable templates, replacing the type::is<T>() / type::as<T>() / type::alt<I>() function syntax.
  • Added $(pattern) callable syntax for $, replacing bind(pattern).
  • Added implicit lit wrapping so value >> handler works without explicit lit(value).
  • Removed bind() entry point; use $ instead.
  • Removed _1, _2, _3 guard aliases; use arg<N> or PTN_WHERE instead.
  • Removed type:: namespace, ds<>(), chained match syntax, and variadic match(subject, cases...) entry.
  • Fixed callable guards failing to dispatch bound values in composed guard expressions (&&, ||) on all compilers.
  • Fixed std::apply-based tuple guard calls producing ICEs on MSVC conformance builds.
  • Fixed PTN_WHERE argument counting under MSVC traditional preprocessor mode.
  • Added vcpkg support (vcpkg install patternia).

API Notes

Named guard with PTN_WHERE:

using namespace ptn;

struct Point { int x; int y; };

bool on_diagonal(const Point &p) {
  return match(p) | on(
    $(has<&Point::x, &Point::y>())[PTN_WHERE((x, y), x == y)] >> true,
    _ >> false
  );
}

Single-value guard with PTN_LET:

using namespace ptn;

const char *bucket(int x) {
  return match(x) | on(
    $[PTN_LET(value, value < 0)] >> "negative",
    $[PTN_LET(value, value < 10)] >> "small",
    _ >> "large"
  );
}

Migration

  • Replace bind() / bind(subpattern) with $ / $(subpattern):
    // before
    bind()[_0 > 0] >> [](int v) { return v; }
    // after
    $[_0 > 0] >> [](int v) { return v; }
  • Replace _1, _2, _3 with arg<N> or PTN_WHERE:
    // before
    $(has<&Point::x, &Point::y>())[_1 == _2] >> "diagonal"
    // after
    $(has<&Point::x, &Point::y>())[PTN_WHERE((x, y), x == y)] >> "diagonal"
  • Replace type::is<T>() / type::as<T>() with is<T> / as<T> variable templates.
  • Replace ds<&T::m...>() with has<&T::m...>().
  • Replace match(subject, cases...) with match(subject) | on(cases...).

Performance

No performance regressions. Guard dispatch rewrites replace std::apply and std::invoke with direct index-sequence expansion, which generates identical or better codegen on MSVC.

Compatibility

This is a breaking release. The following APIs have been removed:

Removed Replacement
bind() $
bind(subpattern) $(subpattern)
_1 / _2 / _3 arg<N> or PTN_WHERE
type::is<T>() / type::as<T>() is<T> / as<T>
ds<&T::m...>() has<&T::m...>()
match(subject, cases...) match(subject) | on(...)
Chained .when(...).otherwise(...) match(subject) | on(...)

Install

vcpkg install patternia
find_package(patternia CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE patternia::patternia)

Docs

  • Release note: docs/changelog/v0.9.0.md

v0.8.3

08 Mar 17:29

Choose a tag to compare

Patternia v0.8.3

Patternia v0.8.3 is an API ergonomics release that introduces shorter, more expressive syntax for common pattern matching operations. All additions are backward-compatible; existing code continues to compile without changes.

Highlights

  • Added match(subject, cases...) as a unified entry point, eliminating the need for builder chains or the pipe operator.
  • Added _ as a wildcard alias for __.
  • Added $ as a concise shorthand for bind().
  • Added _0, _1, _2, _3 as guard placeholder aliases for arg<0> through arg<3>.
  • Deprecated the bare _ guard placeholder (placeholder_t) in favor of _0.
  • Fixed pred_and / pred_or failing to unwrap tuple when invoking raw callables in mixed guard expressions (e.g., _0 > 1u && is_even).

API Notes

Recommended form in v0.8.3:

match(x,
    lit(1) >> 100,
    lit(2) >> 200,
    _ >> 0
);

Value capture with guard:

match(x,
    $[_0 > 0 && _0 < 10] >> [](int v) { return v * 2; },
    _ >> 0
);

All existing forms remain available:

match(x) | on(lit(1) >> 100, __ >> 0);
match(x).when(lit(1) >> 100).otherwise(0);

Migration

  • Replace _ in guard expressions with _0:
    // before
    bind()[_ > 0 && _ < 10]
    // after
    $[_0 > 0 && _0 < 10]
  • No other changes are required. The old _ guard placeholder still compiles but emits a deprecation warning.

Performance

No performance changes in this release. The new match(subject, cases...) entry constructs the same tuple<Cases...> and selects the same dispatch_plan as the existing match(x) | on(...) path. Lowering behavior is identical.

Compatibility

  • No forced migration is required.
  • __, bind(), arg<N>, type::is<T>(), type::as<T>() all remain available.
  • Guard placeholder _ is deprecated; use _0 instead.

Docs

  • Release note: docs/changelog/v0.8.3.md

v0.8.2

03 Mar 06:24

Choose a tag to compare

Patternia v0.8.2

Patternia v0.8.2 is a performance and API refinement release focused on one goal: making keyed pattern chains behave much closer to hand-written switch code while keeping the optimization model scalable.

Highlights

  • Introduced a lowering engine with a shared legality model:
    • full
    • bucketed
    • none
  • Added a switch-oriented static literal dispatch path for lit<value>().
  • Added reusable hot-path matcher forms:
    • static_on(...)
    • PTN_ON(...)
  • Unified static literal dispatch and variant dispatch under the same dispatch_plan model.
  • Public examples now prefer match(x) | on(...).
  • Kept runtime literal factories for general-purpose matching:
    • lit(value)
    • lit_ci(value)

Performance

The main benchmark for this release is a 128-way literal match, chosen to separate dispatch quality from matcher construction overhead.

Representative local results:

Benchmark Meaning CPU time
BM_PatterniaPipe_LiteralMatch128StaticCases prebuilt matcher object 1.74 ns
BM_PatterniaPipe_LiteralMatch128On raw inline on(...) 17.9 ns
BM_PatterniaPipe_LiteralMatch128OnMacro cached pipeline matcher via PTN_ON(...) 2.09 ns
BM_Switch_LiteralMatch128 hand-written switch baseline 1.52 ns

Takeaway:

  • the static literal lowering path is now close to the switch baseline
  • the main remaining cost in raw inline on(...) is matcher construction
  • PTN_ON(...) recovers most of that gap while keeping pipeline syntax

API Notes

Recommended public forms in v0.8.2:

match(x) | on(
  lit(1) >> 1,
  __ >> 0
);

For hot paths:

match(x) | PTN_ON(
  lit<1>() >> 1,
  lit<2>() >> 2,
  __ >> 0
);

Literal API split:

  • lit(value) for general runtime matching
  • lit_ci(value) for runtime case-insensitive string matching
  • lit<value>() for compile-time literal lowering

Compatibility

  • No forced migration is required.
  • Existing on{...} call sites remain source-compatible.
  • Public examples and docs now prefer on(...).

Docs

  • Release note: docs/changelog/v0.8.2.md
  • Performance note: docs/performance/v0.8.2.md

v0.8.0

26 Feb 17:47

Choose a tag to compare

Patternia v0.8.0

Release Date: February 27, 2026
Type: API + Performance Release

Highlights

  • Removed legacy terminal API (breaking):
    • match(x, cases(...)).end()
  • Standardized recommended syntax:
    • match(x) | on{ ... };
  • Introduced tiered variant dispatch:
    • hot_inline (small branch sets)
    • warm_segmented (medium branch sets)
    • cold_compact (large branch sets)
  • Added compact index mapping and cold-path separation for large branch counts.
  • Documentation updates:
    • Refreshed v0.8.0 performance snapshot in README.md
    • Added/updated performance notes under docs/performance
    • Synced changelog and release index for 0.8.0

Breaking Changes

Removed:

  • match(x, cases(...)).end()

Migration

Before

auto r = match(x, cases(
  lit(1) >> [] { return 1; },
  __ >> [] { return 0; }
)).end();

After

auto r = match(x) | on{
  lit(1) >> [] { return 1; },
  __ >> [] { return 0; }
};

Performance Notes

v0.8.0 focuses on variant dispatch improvements:

  • Inline-oriented fast path for small alternative counts
  • Segmented dispatch for medium alternative counts
  • Compact-map + cold-path strategy for large alternative counts
  • Per-alt narrowing in typed-variant dispatch to reduce irrelevant case scanning

Bench & Tooling

  • Use ptn_bench_variant for variant-focused profiling.
  • Generate single-JSON visualization with scripts/bench_single_report.py.
  • README.md now includes benchmark intent, code shape, and interpretation for each variant benchmark group.

Compatibility

  • match(x) | on{...} remains the primary supported path.
  • Chained .when(...).end() and .otherwise(...) are still available but marked as deprecating.

Full Changelog

  • docs/changelog/v0.8.0.md
  • docs/changelog/releases.md

v0.7.6

20 Feb 16:34

Choose a tag to compare

Patternia v0.7.6

Release date: 2026-02-21

Patternia v0.7.6 is a performance + benchmarking release focused on variant dispatch and practical benchmark workflows.

Highlights

  • Variant dispatch fast paths

    • Added single-dispatch fast path for simple variant cases.
    • Specialized simple dispatch by active variant index.
    • Added prefilter path for mixed simple + guarded variant patterns.
    • Simplified typed variant index-resolution internals.
  • Real-world variant benchmarks

    • Added Protocol Router and Command Parser scenarios.
    • Each scenario includes side-by-side implementations:
      • Patternia
      • if-else
      • switch-case
      • std::visit
  • Benchmark tooling

    • Added scripts/bench_single_report.py for single-JSON visualization.
    • Outputs chart + markdown + csv for easier local comparison.
  • Docs updates

    • Moved latest benchmark snapshot to the top of README.
    • Updated benchmark workflow docs and release index.

Compatibility

  • API: unchanged for 0.7.x users.
  • Source compatibility: unchanged.
  • Runtime behavior: external semantics unchanged; optimizations are internal.

Full Changelog

  • perf(variant): prefilter mixed guarded dispatch by active alt
  • refactor(eval): simplify variant simple-dispatch index resolution
  • feat(bench): add protocol router and command parser scenarios
  • feat(scripts): add single-json benchmark visualization tool
  • docs(readme): surface latest benchmark snapshot at top

Compare: v0.7.5...v0.7.6

v0.7.5-Hotfix

18 Feb 12:53

Choose a tag to compare

Patternia v0.7.5 (Hotfix)

Release date: February 18, 2026

Patternia v0.7.5 is a hotfix release for v0.7.4 focused on benchmark build compatibility.

Hotfix Summary

  • Fixed variant benchmark registration that could fail to compile on MinGW toolchains.
  • Replaced macro-as-argument benchmark registration with direct BENCHMARK(...)->... chained configuration.
  • Preserved the same stable variant benchmark profile:
    • nanosecond unit
    • minimum run time
    • repetitions
    • aggregate-only reporting
  • Adjusted alternating-hot microbench setup to avoid deprecated const-ref DoNotOptimize usage.

Impact

  • API: no changes
  • Runtime semantics: no changes
  • Build/tooling: benchmark target now builds correctly on MinGW in scenarios where v0.7.4 could fail

Full Changelog

v0.7.4

18 Feb 12:26

Choose a tag to compare

Patternia v0.7.4

Release date: February 18, 2026

Patternia v0.7.4 is a focused performance and engineering patch release for the 0.7.x line.

Highlights

  • Reduced redundant binding work in guarded match evaluation paths.
  • Reduced typed-eval overhead for zero-bind variant cases.
  • Added guarded-path bind-count regression tests to ensure one-bind behavior on match.
  • Added variant-focused microbench coverage and a more stable benchmark run profile.
  • Improved CI with benchmark gate workflow and tighter default pipeline checks.

Compatibility

  • No breaking API changes for 0.7.x users.
  • Source compatibility remains unchanged.
  • Runtime semantics remain consistent; internal evaluation paths are optimized.

Documentation

  • Added dedicated release note: docs/changelog/v0.7.4.md
  • Updated release index and README versioned benchmark/update sections.

Full Changelog

v0.7.3

16 Feb 14:34

Choose a tag to compare

Patternia v0.7.3 Release Note

Date: February 16, 2026

🎆Happy Chinese NewYear!🎆

What's Changed

Performance: Reference-Oriented Binding

  • Optimized bind() / bind(subpattern) binding paths to avoid unnecessary value copies.
  • Structural member binding now prefers reference-oriented binding, improving heavy payload scenarios.

Heavy-Bind Benchmarking

  • Added BM_Patternia_PacketMixedHeavyBind and BM_Switch_PacketMixedHeavyBind for copy-sensitive performance comparison.
  • Added benchmark result staging and comparison scripts:
    • scripts/bench_stage_results.py
    • scripts/bench_compare.py

Docs and Release Updates

  • README.md now includes v0.7.3 performance notes and heavy-benchmark workflow.
  • Added changelog page: docs/changelog/v0.7.3.md
  • Updated release index and bumped project version to 0.7.3.

Full release notes: v0.7.3.md

v0.7.1

06 Feb 16:58

Choose a tag to compare

Patternia v0.7.1 Release Note

Date: February 7, 2026

What's Changed

Diagnostics Quality Improvements

This patch release focuses on clearer compile-time diagnostics and better developer guidance.

Highlights:

  • Replaced generic static_assert requirement names (like ok) with semantic names
  • Added concise Tip: hints to common match-builder diagnostics
  • Improved type::is<T>() diagnostics for:
    • alternative type not found in std::variant
    • duplicate alternative types (with guidance to use type::alt<I>)

No API or Runtime Behavior Changes

  • API surface is unchanged
  • Matching behavior is unchanged
  • This is a developer-experience (DX) patch release

Full release notes: v0.7.1.md

v0.7.0

04 Feb 17:26

Choose a tag to compare

Patternia v0.7.0 Release Note

Date: February 5, 2026

What's Changed

Variant Matching

Patternia now supports std::variant matching with a unified type-pattern system.

New/Updated APIs:

  • type::is<T> — type match
  • type::as<T> — type match + binding
  • type::alt<I> — index-based match (supports duplicated types)

Example:

auto r = match(v)
  .when(type::is<int>() >> "int")
  .when(type::as<std::string>() >> [](const std::string &s) { return s; })
  .when(__ >> "other")
  .end();

Guards on Binding Type Patterns

Type patterns that bind can now participate in guards:

.when(type::as<std::string>()[ _ != "" ] >> [](const std::string &s) { ... })

Diagnostics Improvements

  • Shorter, clearer static_assert messages
  • Consistent diagnostic prefixes
  • Structural has<> members validated at match-time

Documentation Updates

  • Variant matching docs expanded
  • Binding/guard semantics clarified
  • Navigation link fixes

Full release notes: v0.7.0.md