Getting Started¶
Install¶
git clone https://github.com/SentoMK/patternia.git
cd patternia
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build
Patternia is header-only.
Including ptn/patternia.hpp is enough to use the library.
First Match¶
#include <ptn/patternia.hpp>
int classify(int x) {
using namespace ptn;
return match(x) | on(
lit(0) >> 0,
lit(5) >> 5,
_ >> -1
);
}
Read this as:
- Start matching
x. - Try the cases in order.
- Use
_for the final fallback.
Side Effects and Returned Values¶
Patternia matches are expressions. Handlers can return values or perform side effects.
using namespace ptn;
void log_value(int x) {
match(x) | on(
lit(1) >> [] { std::cout << "one\n"; },
lit(2) >> [] { std::cout << "two\n"; },
_ >> [] { std::cout << "other\n"; }
);
}
using namespace ptn;
int score(int x) {
return match(x) | on(
lit(1) >> 100,
lit(2) >> 200,
_ >> 0
);
}
Binding¶
Use $ or $(...) when the handler needs data from the match.
using namespace ptn;
int identity(int x) {
return match(x) | on(
$ >> [](int v) { return v; },
_ >> 0
);
}
Use $ to bind the whole subject.
Use $(...) to bind under a subpattern.
Guards¶
Attach a guard with [].
using namespace ptn;
const char *bucket(int x) {
return match(x) | on(
$[PTN_LET(value, value > 0 && value < 10)] >> "small",
_ >> "other"
);
}
For multiple bound values, use arg<N> or PTN_WHERE((...), expr):
using namespace ptn;
struct Point {
int x;
int y;
};
bool on_unit_circle(const Point &p) {
return match(p) | on(
$(has<&Point::x, &Point::y>)[arg<0> * arg<0> + arg<1> * arg<1> == 1]
>> true,
_ >> false
);
}
using namespace ptn;
bool on_diagonal(const Point &p) {
return match(p) | on(
$(has<&Point::x, &Point::y>)[PTN_WHERE((x, y), x == y)] >> true,
_ >> false
);
}
Structural Matching¶
Use has<> to describe object structure and $(...) to bind selected members.
using namespace ptn;
struct Point {
int x;
int y;
};
int sum(const Point &p) {
return match(p) | on(
$(has<&Point::x, &Point::y>) >> [](int x, int y) {
return x + y;
},
_ >> 0
);
}
Variant Matching¶
Use is<T> for type-based dispatch and alt<I> for index-based dispatch.
using namespace ptn;
using Value = std::variant<int, std::string>;
std::string describe(const Value &v) {
return match(v) | on(
is<int> >> "int",
$(is<std::string>) >> [](const std::string &s) {
return "str:" + s;
},
_ >> [] { return std::string("other"); }
);
}
Cached Hot Paths¶
If the same case pack is reused on a hot path, cache it:
using namespace ptn;
int classify_fast(int x) {
return match(x) | PTN_ON(
val<1> >> 1,
val<2> >> 2,
_ >> 0
);
}
Or:
using namespace ptn;
int classify_fast(int x) {
return match(x) | static_on([] {
return on(
val<1> >> 1,
val<2> >> 2,
_ >> 0
);
});
}
Tests¶
cmake -S . -B build -DPTN_BUILD_TESTS=ON
cmake --build build --target ptn_tests
ctest --test-dir build --output-on-failure
Next¶
- Read the API reference
- Read the design overview
- Continue with the tutorials under
docs/tutorials/