Skip to content

Latest commit

 

History

History
434 lines (361 loc) · 10.2 KB

211.md

File metadata and controls

434 lines (361 loc) · 10.2 KB
Info

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
  };
}

https://godbolt.org/z/efE3va

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}));
  };
}

https://godbolt.org/z/fEnb8c

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}));
};

https://godbolt.org/z/E9W5za

"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}));
};

https://godbolt.org/z/ePMTKo

  "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}));
  };

https://godbolt.org/z/Wj5jhv

"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}));
};

https://godbolt.org/z/7Y3jas

"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}));
};

https://godbolt.org/z/o9xqvx

"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}));
};

https://godbolt.org/z/nzMKeT

"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}));
};

https://godbolt.org/z/sea88v

"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}));
};

https://godbolt.org/z/vojTqd