// // accumulate.h // stream // // Created by Sam Jaffe on 3/29/23. // #pragma once #include #include #include #define FWD(x) std::forward(x) namespace stream::ranges { template auto fold_left(It it, S end, T init, F reduce) { for (; it != end; ++it) { init = reduce(init, *it); } return init; } template auto fold_left(Stream && stream, T init, F reduce) { for (auto && elem : FWD(stream)) { init = reduce(init, FWD(elem)); } return init; } template auto fold_left_with_first(Stream && stream, F reduce) -> std::optional> { if (stream.empty()) { return std::nullopt; } return fold_left(++stream.begin(), stream.end(), *stream.begin(), reduce); } template auto first(Stream && stream) -> std::optional> { return stream.empty() ? std::nullopt : std::optional(*stream.begin()); } template bool any_of(It it, S end, Pred pred, Proj proj = {}) { for (; it != end; ++it) { if (pred(proj(*it))) { return true; } } return false; } template bool any_of(Stream const & stream, Pred pred, Proj proj = {}) { return any_of(stream.begin(), stream.end(), pred, proj); } template bool none_of(It it, S end, Pred pred, Proj proj = {}) { return !any_of(it, end, pred, proj); } template bool none_of(Stream const & stream, Pred pred, Proj proj = {}) { return none_of(stream.begin(), stream.end(), pred, proj); } template bool all_of(It it, S end, Pred pred, Proj proj = {}) { for (; it != end; ++it) { if (!pred(proj(*it))) { return false; } } return true; } template bool all_of(Stream const & stream, Pred pred, Proj proj = {}) { return all_of(stream.begin(), stream.end(), pred, proj); } } #undef FWD