Example
int main() {
auto value = 42;
inspect (value) {
0 => { std::cout << 0; }
42 => { std::cout << 42; } // prints 42
x => { std::cout << x; }
};
auto tuple = std::tuple{"Quantlab", 42};
inspect(tuple) {
[str, 42] => { std::cout << str << ' ' << 42; } // prints Quantlab42
[_, _] => { std::cout << "..."; }
};
return inspect(value) {
_ => _ + 1; // returns 43
};
}
Puzzle
- Can you apply pattern matching to the following use cases {integral, enum, tuple}?
int main() {
using namespace boost::ut;
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
_ => 0; // TODO
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
const auto inspect_expr = [](const std::size_t value) {
return inspect(value) {
// TODO
};
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(value) {
// TODO
};
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};
}
Solutions
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
_ => 42;
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
const auto inspect_expr = [](const std::size_t value) {
return inspect(value) {
'+' => op::Add;
'-' => op::Sub;
'*' => op::Mul;
'/' => op::Div;
_ => !{throw 0;}
};
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(value) {
[0, _] => 0;
[_, 0] => 0;
[x, y] => x + y;
};
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
x => x;
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
constexpr auto inspect_expr = [](const std::size_t value) {
return inspect(value) {
'+' => op::Add;
'-' => op::Sub;
'*' => op::Mul;
'/' => op::Div;
_ => !{ throw std::runtime_error("Nope"); };
};
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(value) {
[0, x] => 0;
[x, 0] => 0;
[x, y] => x+y;
};
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
_ => _;
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
const auto inspect_expr = [](const std::size_t value) {
return inspect(value) {
'+' => op::Add;
'-' => op::Sub;
'*' => op::Mul;
'/' => op::Div;
_ => !{ throw std::invalid_argument{"Only arithmetic operations"}; }
};
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(value) {
[0, _] => 0;
[_, 0] => 0;
[x, y] => x + y;
};
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
_ => value;
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
const auto inspect_expr = [](const std::size_t value) {
return inspect(value) {
'+' => op::Add;
'-' => op::Sub;
'*' => op::Mul;
'/' => op::Div;
_ => throw(1), op::Add;
};
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(std::get<0>(value)+std::get<1>(value)) {
3 => 3;
_ => 0;
};
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
_ => value;
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
const auto inspect_expr = [](const std::size_t value) ->op{
return inspect(value) {
'+'=>op::Add;
'-'=>op::Sub;
'*'=>op::Mul;
'/'=>op::Div;
_ =>!{throw std::runtime_error("Not Supported");}
};
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(value) {
[0,_]=>0;
[_,0]=>0;
[x,y]=>x+y;
};
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
x => x;
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
const auto inspect_expr = [](const std::size_t value) {
return inspect(value) {
'+' => op::Add;
'-' => op::Sub;
'*' => op::Mul;
'/' => op::Div;
_ => !{ throw std::invalid_argument("value"); }
};
throw;
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(value) {
[0, _] => 0;
[_, 0] => 0;
[u, v] => u + v;
};
throw;
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
_ => _;
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
const auto inspect_expr = [](const std::size_t value) {
return inspect(value) {
'+' => op::Add;
'-' => op::Sub;
'*' => op::Mul;
'/' => op::Div;
_ => !{
throw std::invalid_argument("Could not parse argument");
}
};
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(value) {
// Not sure if there's some algorithm at play here that I'm not seeing - the tests don't seem correlated to me.
[0, 2] => 0;
[1, 0] => 0;
[1, 2] => 3;
};
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};
"pattern matching - integral"_test = [value = 42u] {
expect(value == inspect(value) {
_ => value;
});
};
"pattern matching - enum"_test = [] {
enum class op { Add, Sub, Mul, Div };
const auto inspect_expr = [](const std::size_t value) {
return inspect (value) {
'+' => op::Add;
'-' => op::Sub;
'*' => op::Mul;
'/' => op::Div;
' ' => !{throw std::runtime_error("inspect_expr not there");}
};
};
expect(op::Add == inspect_expr('+'));
expect(op::Sub == inspect_expr('-'));
expect(op::Mul == inspect_expr('*'));
expect(op::Div == inspect_expr('/'));
expect(throws( [=] { inspect_expr(' '); }));
};
"pattern matching - tuple"_test = [] {
const auto inspect_expr = [](const std::tuple<int, int>& value) {
return inspect(value) {
[0, _] => 0;
[_, 0] => 0;
[x, y] => x + y;
};
};
expect(0_i == inspect_expr(std::tuple{0, 2}));
expect(0_i == inspect_expr(std::tuple{1, 0}));
expect(3_i == inspect_expr(std::tuple{1, 2}));
};