2022-09-23 16:42:33 +02:00
|
|
|
#ifndef MUSIQUE_ALGO_HH
|
|
|
|
#define MUSIQUE_ALGO_HH
|
|
|
|
|
|
|
|
#include <musique/result.hh>
|
|
|
|
#include <musique/try.hh>
|
2022-09-23 18:55:25 +02:00
|
|
|
#include <musique/value/value.hh>
|
2022-09-23 16:42:33 +02:00
|
|
|
#include <ranges>
|
2022-10-14 14:40:01 +02:00
|
|
|
#include <compare>
|
2022-09-23 16:42:33 +02:00
|
|
|
|
|
|
|
/// Generic algorithms support
|
|
|
|
namespace algo
|
|
|
|
{
|
|
|
|
/// Check if predicate is true for all successive pairs of elements
|
|
|
|
constexpr bool pairwise_all(
|
2022-10-14 14:40:01 +02:00
|
|
|
auto &&range,
|
2022-09-23 16:42:33 +02:00
|
|
|
auto &&binary_predicate)
|
|
|
|
{
|
|
|
|
auto it = std::begin(range);
|
|
|
|
auto const end_it = std::end(range);
|
|
|
|
for (auto next_it = std::next(it); it != end_it && next_it != end_it; ++it, ++next_it) {
|
|
|
|
if (not binary_predicate(*it, *next_it)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Fold that stops iteration on error value via Result type
|
|
|
|
template<typename T>
|
|
|
|
constexpr Result<T> fold(auto&& range, T init, auto &&reducer)
|
|
|
|
requires (is_template_v<Result, decltype(reducer(std::move(init), *range.begin()))>)
|
|
|
|
{
|
|
|
|
for (auto &&value : range) {
|
|
|
|
init = Try(reducer(std::move(init), value));
|
|
|
|
}
|
|
|
|
return init;
|
|
|
|
}
|
2022-10-14 14:40:01 +02:00
|
|
|
|
|
|
|
/// Equavilent of std::lexicographical_compare_three_way
|
|
|
|
///
|
|
|
|
/// It's missing from MacOS C++ standard library
|
|
|
|
constexpr auto lexicographical_compare(auto&& lhs_range, auto&& rhs_range)
|
|
|
|
{
|
|
|
|
auto lhs = lhs_range.begin();
|
|
|
|
auto rhs = rhs_range.begin();
|
|
|
|
decltype(*lhs <=> *rhs) result = std::partial_ordering::equivalent;
|
|
|
|
for (; lhs != lhs_range.end() && rhs != rhs_range.end(); ++lhs, ++rhs) {
|
|
|
|
if ((result = *lhs <=> *rhs) != 0) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2022-09-23 16:42:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Flattens one layer: `[[[1], 2], 3]` becomes `[[1], 2, 3]`
|
|
|
|
Result<std::vector<Value>> flatten(Interpreter &i, std::span<Value>);
|
|
|
|
Result<std::vector<Value>> flatten(Interpreter &i, std::vector<Value>);
|
|
|
|
|
|
|
|
#endif
|