Patternia v0.9.0 Release Note¶
Release Date: March 13, 2026 Version: 0.9.0
Overview¶
Patternia v0.9.0 is an API modernization and compiler compatibility release.
It introduces PTN_WHERE and PTN_LET as the canonical named-guard syntax,
removes the legacy bind() entry point and positional guard aliases _1/_2/_3,
and ships a series of fixes that make callable guards work correctly across
GCC, Clang, and MSVC. vcpkg packaging support is also added in this version.
Highlights¶
Named Guard Macros: PTN_WHERE and PTN_LET¶
PTN_WHERE((names...), expr) gives guard arguments explicit names without
writing a lambda. It supports 1 to 5 bound values:
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
);
}
PTN_LET(name, expr) is the single-value shorthand, equivalent to
PTN_WHERE((name), expr):
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"
);
}
Both macros expand to captureless guard callables and compose with && / ||
like other guard predicates.
API Cleanup: bind() and _1/_2/_3 Removed (Breaking)¶
The legacy bind() entry point and the positional guard aliases _1, _2,
_3 have been removed from the public surface.
Migrate to the current equivalents:
| Removed | Replacement |
|---|---|
bind() |
$ |
bind(subpattern) |
$(subpattern) |
_1 |
arg<0> or PTN_LET |
_2 |
arg<1> |
_3 |
arg<2> |
A compile-fail test covers both removed names to prevent silent regressions.
Callable Guard Fixes for MSVC and Standard C++¶
Four guard fixes were shipped in this cycle:
- Callable guards evaluate as tuple predicates. The guard trait system
now classifies
callable_guardcorrectly soPTN_WHERE/PTN_LETparticipate in composed guard evaluation (&&,||) on all compilers. - Replaced
std::applyin tuple guard calls with an explicit index sequence expansion to avoid MSVC ICEs on conformance-mode builds. - Replaced
std::invokein callable guard dispatch with direct call syntax for the same reason. - MSVC traditional preprocessor workaround for
PTN_WHEREargument counting via__VA_ARGS__indirection.
These fixes have no effect on GCC and Clang builds. MSVC users with
/Zc:preprocessor enabled are not affected either.
vcpkg Support¶
Patternia is now available through the vcpkg package manager:
vcpkg install patternia
Or via vcpkg.json manifest:
{
"dependencies": ["patternia"]
}
Consume through the existing CMake target:
find_package(patternia CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE patternia::patternia)
Migration Notes¶
bind() removed¶
// Before
match(x) | on(
bind()[_0 > 0] >> [](int v) { return v; },
_ >> 0
);
// After
match(x) | on(
$[_0 > 0] >> [](int v) { return v; },
_ >> 0
);
_1/_2/_3 removed¶
// Before
$(has<&Point::x, &Point::y>())[_1 == _2] >> "diagonal"
// After
$(has<&Point::x, &Point::y>())[arg<0> == arg<1>] >> "diagonal"
// or
$(has<&Point::x, &Point::y>())[PTN_WHERE((x, y), x == y)] >> "diagonal"
Bug Fixes¶
- Fixed
PTN_WHEREargument counting failing under MSVC traditional preprocessor mode. Added__VA_ARGS__indirection as a standard workaround. No effect on conforming preprocessors. - Fixed callable guards failing to dispatch bound values correctly in
composed guard expressions by routing them through the tuple predicate
path instead of
std::invoke. - Fixed
std::apply-based tuple guard calls producing ICEs on MSVC conformance builds.
Internal¶
include/ptn/pattern/modifiers/guard.hpp: addedcallable_guardtype andmake_callable_guard, rewrote tuple expansion withoutstd::applyorstd::invoke.include/ptn/pattern/base/pattern_traits.hpp,modifiers/fwd.h: addedcallable_guardto the guard trait classifier.include/ptn/patternia.hpp: addedPTN_WHEREandPTN_LETmacros, removedbindand_1/_2/_3exports.tests/compile_fail/: addedbind_function_removed.cppandguard_placeholder_alias_removed.cpp.