32# ifndef AH_STL_FUNCTIONAL_H
33# define AH_STL_FUNCTIONAL_H
74# include <type_traits>
84# include <unordered_set>
85# include <unordered_map>
100 template <
typename T,
typename =
void>
103 template <
typename T>
107 template <
typename T>
111 template <
typename T,
typename =
void>
114 template <
typename T>
116 std::
void_t<decltype(std::hash<T>{}(std::declval<T>()))>>
119 template <
typename T>
123 template <
typename T,
typename =
void>
126 template <
typename T>
128 std::
void_t<decltype(std::declval<T>().rbegin()),
129 decltype(std::declval<T>().rend())>>
132 template <
typename T>
136 template <
typename Container>
146 template <
typename Result,
typename Container>
150 result.reserve(c.size());
154 template <
typename Result>
157 if constexpr (
requires { result.reserve(n); })
184 template <
typename T =
int>
187 std::vector<T> result;
190 result.reserve(
static_cast<size_t>((end - start) /
step + 1));
191 for (
T i = start; i <= end; i +=
step)
196 result.reserve(
static_cast<size_t>((start - end) / (-
step) + 1));
197 for (
T i = start; i >= end; i +=
step)
212 template <
typename T =
int>
215 std::vector<T> result;
216 result.reserve(
static_cast<size_t>(n));
217 for (
T i = 0; i < n; ++i)
233 template <
typename T =
double>
236 std::vector<T> result;
237 if (n == 0)
return result;
241 result.push_back(start);
246 const auto step = (end - start) /
static_cast<T>(n - 1);
247 for (
size_t i = 0; i < n; ++i)
248 result.push_back(start +
static_cast<T>(i) *
step);
262 template <
typename T>
265 return std::vector<T>(n, value);
278 template <
typename Gen>
281 using T = std::decay_t<
decltype(
gen(
size_t{}))>;
282 std::vector<T> result;
285 for (
size_t i = 0; i < n; ++i)
303 template <
typename Op,
typename Container>
307 for (
const auto & item: c)
320 template <
typename Op,
typename Container>
325 for (
const auto & item: c)
344 template <
typename Op,
typename Container>
347 using T =
typename Container::value_type;
348 using R = std::decay_t<decltype(op(std::declval<T>()))>;
350 std::vector<R> result;
353 for (
const auto & item: c)
354 result.push_back(
op_ref(item));
368 template <
typename Op,
typename Container>
371 using T =
typename Container::value_type;
372 using R = std::decay_t<
decltype(op(
size_t{}, std::declval<T>()))>;
374 std::vector<R> result;
378 for (
const auto & item: c)
379 result.push_back(
op_ref(i++, item));
393 template <
typename Pred,
typename Container>
396 using T =
typename Container::value_type;
398 std::vector<T> result;
400 for (
const auto & item: c)
402 result.push_back(item);
416 template <
typename Pred,
typename Container>
419 using T =
typename Container::value_type;
421 std::vector<T> result;
424 for (
const auto & item: c)
427 result.push_back(item);
451 template <
typename T,
typename Op,
typename Container>
455 if constexpr (std::ranges::range<Container>)
462 for (
const auto & item: c)
489 template <
typename T,
typename Op,
typename Container>
492 static_assert(stl_detail::has_reverse_iterators_v<Container>,
493 "stl_foldr requires a container with reverse iterators (rbegin/rend)");
496 for (
auto it = c.rbegin(); it != c.rend(); ++it)
518 template <
typename T,
typename Op,
typename Container>
521 std::vector<T> result;
522 if constexpr (stl_detail::has_size_v<Container>)
523 result.reserve(c.size() + 1);
524 result.push_back(
init);
528 for (
const auto & item: c)
531 result.push_back(
acc);
547 template <
typename T,
typename Op,
typename Container>
550 static_assert(stl_detail::has_reverse_iterators_v<Container>,
551 "stl_scan_right requires a container with reverse iterators (rbegin/rend)");
552 std::vector<T> result;
553 if constexpr (stl_detail::has_size_v<Container>)
554 result.reserve(c.size() + 1);
557 result.push_back(
acc);
560 for (
auto it = c.rbegin(); it != c.rend(); ++it)
563 result.push_back(
acc);
566 std::reverse(result.begin(), result.end());
571 template <
typename T,
typename Op,
typename Container>
591 template <
typename Pred,
typename Container>
595 if constexpr (std::ranges::range<Container>)
601 for (
const auto & item: c)
618 template <
typename Pred,
typename Container>
622 if constexpr (std::ranges::range<Container>)
628 for (
const auto & item: c)
636 template <
typename Pred,
typename Container>
648 template <
typename Pred,
typename Container>
668 template <
typename Pred,
typename Container>
671 using T =
typename Container::value_type;
674 for (
const auto & item: c)
676 return std::optional<T>(item);
677 return std::optional<T>{};
690 template <
typename Pred,
typename Container>
693 using T =
typename Container::value_type;
695 std::optional<T> result;
697 for (
const auto & item: c)
713 template <
typename Pred,
typename Container>
718 for (
const auto & item: c)
737 template <
typename Op,
typename Container>
740 using T =
typename Container::value_type;
741 using OptType = std::decay_t<
decltype(op(
size_t{}, std::declval<T>()))>;
742 static_assert(std::is_default_constructible_v<OptType>,
743 "stl_find_mapi requires the return type to be default-constructible (like std::optional)");
747 for (
const auto & item: c)
748 if (
auto result =
op_ref(i++, item))
763 template <
typename T,
typename Container>
766 for (
const auto & item: c)
786 template <
typename Pred,
typename Container>
791 for (
const auto & item: c)
807 template <
typename T,
typename Container>
811 for (
const auto & item: c)
831 template <
typename Container>
834 using T =
typename Container::value_type;
836 std::vector<T> result;
839 for (
const auto & item: c)
841 if (
count >= n)
break;
842 result.push_back(item);
858 template <
typename Container>
861 using T =
typename Container::value_type;
863 std::vector<T> result;
864 if constexpr (stl_detail::has_size_v<Container>)
866 if (
const size_t size = c.size();
size > n)
867 result.reserve(
size - n);
870 for (
const auto & item: c)
873 result.push_back(item);
889 template <
typename Container>
892 using T =
typename Container::value_type;
894 std::vector<T> result;
898 if constexpr (!stl_detail::has_size_v<Container>)
901 std::vector<T>
all(c.begin(), c.end());
903 const size_t skip =
size > n ? (
size - n) : 0;
904 result.reserve(
size > n ? n :
size);
905 for (
size_t i = skip; i <
size; ++i)
906 result.push_back(std::move(
all[i]));
913 const size_t skip =
size > n ? (
size - n) : 0;
916 for (
const auto & item: c)
919 result.push_back(item);
936 template <
typename Pred,
typename Container>
939 using T =
typename Container::value_type;
941 std::vector<T> result;
943 for (
const auto & item: c)
947 result.push_back(item);
962 template <
typename Pred,
typename Container>
965 using T =
typename Container::value_type;
967 std::vector<T> result;
970 for (
const auto & item: c)
975 result.push_back(item);
993 template <
typename Container>
996 using T =
typename Container::value_type;
1000 return std::optional<T>{};
1001 return std::optional<T>(*it);
1013 template <
typename Container>
1016 using T =
typename Container::value_type;
1018 auto it = c.begin();
1020 return std::optional<T>{};
1023 if constexpr (stl_detail::has_reverse_iterators_v<Container>)
1025 return std::optional<T>(*c.rbegin());
1032 for (; it != c.end(); ++it)
1034 return std::optional<T>(last);
1048 template <
typename Container>
1051 using T =
typename Container::value_type;
1054 for (
const auto & item: c)
1057 return std::optional<T>(item);
1060 return std::optional<T>{};
1076 template <
typename Container>
1079 using T =
typename Container::value_type;
1081 auto it = c.begin();
1083 return std::optional<T>{};
1087 for (; it != c.end(); ++it)
1090 return std::optional<T>(
min_val);
1102 template <
typename Container>
1105 using T =
typename Container::value_type;
1107 auto it = c.begin();
1109 return std::optional<T>{};
1113 for (; it != c.end(); ++it)
1116 return std::optional<T>(
max_val);
1128 template <
typename Container>
1131 using T =
typename Container::value_type;
1132 using ResultType = std::optional<std::pair<T, T>>;
1134 auto it = c.begin();
1142 for (; it != c.end(); ++it)
1160 template <
typename Key,
typename Container>
1163 using T =
typename Container::value_type;
1165 auto it = c.begin();
1167 return std::optional<T>{};
1174 for (; it != c.end(); ++it)
1196 template <
typename Key,
typename Container>
1199 using T =
typename Container::value_type;
1201 auto it = c.begin();
1203 return std::optional<T>{};
1210 for (; it != c.end(); ++it)
1235 template <
typename Container>
1238 using T =
typename Container::value_type;
1240 for (
const auto & item: c)
1254 template <
typename Container>
1257 using T =
typename Container::value_type;
1258 if (c.empty())
return T{};
1260 auto it = c.begin();
1263 for (; it != c.end(); ++it)
1282 template <
typename Pred,
typename Container>
1285 using T =
typename Container::value_type;
1289 for (
const auto & item: c)
1311 template <
typename Container1,
typename Container2>
1314 using T1 =
typename Container1::value_type;
1315 using T2 =
typename Container2::value_type;
1317 std::vector<std::pair<T1, T2>> result;
1318 if constexpr (stl_detail::has_size_v<Container1> && stl_detail::has_size_v<Container2>)
1323 result.emplace_back(*it1, *it2);
1336 template <
typename Container>
1339 using PairType =
typename Container::value_type;
1340 using T1 = std::decay_t<decltype(std::declval<PairType>().first)>;
1341 using T2 = std::decay_t<decltype(std::declval<PairType>().second)>;
1348 for (
const auto & p: c)
1350 v1.push_back(p.first);
1351 v2.push_back(p.second);
1353 return std::make_pair(std::move(v1), std::move(v2));
1365 template <
typename Container>
1368 using T =
typename Container::value_type;
1370 std::vector<std::pair<size_t, T>> result;
1373 for (
const auto & item: c)
1374 result.emplace_back(i++, item);
1392 template <
typename Container1,
typename Container2>
1398 if (
not (*it1 == *it2))
1413 template <
typename Container1,
typename Container2>
1421 if (*it1 < *it2)
return -1;
1422 if (*it2 < *it1)
return 1;
1426 return (it1 ==
c1.
end()) ? -1 : 1;
1442 template <
typename Container>
1445 using T =
typename Container::value_type;
1447 std::vector<T> result(c.begin(), c.end());
1448 std::reverse(result.begin(), result.end());
1461 template <
typename Container>
1464 using T =
typename Container::value_type;
1466 std::vector<T> result(c.begin(), c.end());
1467 std::sort(result.begin(), result.end());
1481 template <
typename Cmp,
typename Container>
1484 using T =
typename Container::value_type;
1486 std::vector<T> result(c.begin(), c.end());
1489 std::sort(result.begin(), result.end(), std::forward<Cmp>(
cmp));
1506 template <
typename Container>
1509 using T =
typename Container::value_type;
1511 std::vector<T> result;
1512 for (
const auto & item: c)
1513 if (result.empty()
or not (result.back() == item))
1514 result.push_back(item);
1544 template <
typename Container>
1547 using T =
typename Container::value_type;
1549 std::vector<T> result;
1553 if constexpr (!stl_detail::is_std_hashable_v<T>)
1556 for (
const auto & item : c)
1557 if (std::find(result.begin(), result.end(), item) == result.end())
1558 result.push_back(item);
1563 for (
const auto & item : c)
1564 if (std::find(result.begin(), result.end(), item) == result.end())
1565 result.push_back(item);
1570 std::unordered_set<T>
seen;
1572 for (
const auto & item : c)
1574 result.push_back(item);
1594 template <
typename Container1,
typename Container2>
1597 using T =
typename Container1::value_type;
1599 std::vector<T> result;
1600 if constexpr (stl_detail::has_size_v<Container1> && stl_detail::has_size_v<Container2>)
1602 for (
const auto & item:
c1)
1603 result.push_back(item);
1604 for (
const auto & item:
c2)
1605 result.push_back(item);
1618 template <
typename Container>
1622 using T =
typename InnerContainer::value_type;
1624 std::vector<T> result;
1625 for (
const auto &
inner: c)
1626 for (
const auto & item:
inner)
1627 result.push_back(item);
1641 template <
typename Op,
typename Container>
1644 using T =
typename Container::value_type;
1645 using InnerContainer = std::decay_t<decltype(op(std::declval<T>()))>;
1646 using R =
typename InnerContainer::value_type;
1648 std::vector<R> result;
1650 for (
const auto & item: c)
1669 template <
typename Container>
1672 using T =
typename Container::value_type;
1674 std::vector<std::vector<T>> result;
1675 if (c.empty())
return result;
1677 auto it = c.begin();
1678 result.emplace_back();
1679 result.back().push_back(*it);
1683 for (; it != c.end(); ++it)
1685 if (
not (*it == current))
1687 result.emplace_back();
1690 result.back().push_back(*it);
1724 template <
typename Key,
typename Container>
1727 using T =
typename Container::value_type;
1728 using K = std::decay_t<decltype(key(std::declval<T>()))>;
1730 std::vector<std::pair<K, std::vector<T>>> result;
1735 if constexpr (!stl_detail::is_std_hashable_v<K>)
1738 for (
const auto & item : c)
1741 auto it = std::find_if(result.begin(), result.end(),
1742 [&
k](
const auto & p) { return p.first == k; });
1743 if (it != result.end())
1744 it->second.push_back(item);
1746 result.emplace_back(std::move(
k), std::vector<T>{item});
1752 for (
const auto & item : c)
1755 auto it = std::find_if(result.begin(), result.end(),
1756 [&
k](
const auto & p) { return p.first == k; });
1757 if (it != result.end())
1758 it->second.push_back(item);
1760 result.emplace_back(std::move(
k), std::vector<T>{item});
1769 for (
const auto & item : c)
1774 result.emplace_back(std::move(
k), std::vector<T>{item});
1776 result[it->second].second.push_back(item);
1787 namespace stl_comb_detail
1789 template <
typename T,
typename Op>
1792 if (start >= arr.size())
1795 for (
size_t i = start; i < arr.size(); ++i)
1797 std::swap(arr[start], arr[i]);
1800 std::swap(arr[start], arr[i]);
1803 std::swap(arr[start], arr[i]);
1808 template <
typename T,
typename Op>
1810 std::vector<T> & current,
Op &
op_ref)
1812 if (current.size() ==
k)
1815 for (
size_t i = start; i <= arr.size() - (
k - current.
size()); ++i)
1817 current.push_back(arr[i]);
1828 template <
typename T,
typename Op>
1830 std::vector<T> & current, std::vector<bool> &
used,
Op &
op_ref)
1832 if (current.size() ==
k)
1835 for (
size_t i = 0; i < arr.size(); ++i)
1837 if (
used[i])
continue;
1839 current.push_back(arr[i]);
1876 template <
typename Op,
typename Container>
1879 using T =
typename Container::value_type;
1880 std::vector<T> arr(c.begin(), c.end());
1896 template <
typename Container>
1899 using T =
typename Container::value_type;
1900 std::vector<std::vector<T>> result;
1904 result.push_back(p);
1935 template <
typename Op,
typename Container>
1938 using T =
typename Container::value_type;
1939 std::vector<T> arr(c.begin(), c.end());
1944 std::vector<T> current;
1960 template <
typename Container>
1963 using T =
typename Container::value_type;
1964 std::vector<std::vector<T>> result;
1968 result.push_back(
combo);
1999 template <
typename Op,
typename Container>
2002 using T =
typename Container::value_type;
2003 std::vector<T> arr(c.begin(), c.end());
2008 std::vector<T> current;
2010 std::vector<bool>
used(arr.size(),
false);
2025 template <
typename Container>
2028 using T =
typename Container::value_type;
2029 std::vector<std::vector<T>> result;
2033 result.push_back(arr);
2056 template <
typename T>
2059 std::vector<std::vector<T>> result;
2066 result.push_back({
elem});
2072 for (
const auto &
partial: result)
2094 template <
typename Container>
2097 using T =
typename Container::value_type;
2098 std::vector<T> arr(c.begin(), c.end());
2099 std::vector<std::vector<T>> result;
2101 const size_t n = arr.size();
2105 throw std::overflow_error(
"stl_power_set: container too large (n >= 63 would overflow)");
2107 const size_t total = 1ULL << n;
2108 result.reserve(total);
2110 for (
size_t mask = 0; mask < total; ++mask)
2112 std::vector<T> subset;
2113 for (
size_t i = 0; i < n; ++i)
2114 if (mask & (1ULL << i))
2115 subset.push_back(arr[i]);
2116 result.push_back(std::move(subset));
2142 template <
typename Container>
2145 using T =
typename Container::value_type;
2146 std::vector<std::vector<T>> result;
2148 if (n == 0)
return result;
2150 std::vector<T> arr(c.begin(), c.end());
2151 if (arr.size() < n)
return result;
2153 for (
size_t i = 0; i <= arr.size() - n; ++i)
2154 result.emplace_back(arr.begin() + i, arr.begin() + i + n);
2175 template <
typename Container>
2178 using T =
typename Container::value_type;
2179 std::vector<std::vector<T>> result;
2181 if (n == 0)
return result;
2183 std::vector<T> arr(c.begin(), c.end());
2185 for (
size_t i = 0; i < arr.size(); i += n)
2187 size_t end = std::min(i + n, arr.size());
2188 result.emplace_back(arr.begin() + i, arr.begin() + end);
2210 template <
typename T,
typename Container>
2213 std::vector<T> result;
2216 for (
const auto & item: c)
2219 result.push_back(sep);
2220 result.push_back(item);
2237 template <
typename Container>
2240 using T =
typename Container::value_type;
2242 std::vector<T> first, second;
2244 for (
const auto & item: c)
2247 first.push_back(item);
2249 second.push_back(item);
2253 return std::make_pair(std::move(first), std::move(second));
2268 template <
typename Pred,
typename Container>
2271 using T =
typename Container::value_type;
2273 std::vector<T> first, second;
2274 auto & pred_ref =
pred;
2277 for (
const auto & item: c)
2278 if (taking and pred_ref(item))
2279 first.push_back(item);
2283 second.push_back(item);
2286 return std::make_pair(std::move(first), std::move(second));
2298 template <
typename Container>
2301 using T =
typename Container::value_type;
2302 std::vector<T> arr(c.begin(), c.end());
2304 if (not arr.empty())
2319 template <
typename Container>
2322 using T =
typename Container::value_type;
2323 std::vector<T> result;
2326 for (
const auto & item: c)
2331 result.push_back(item);
2361 template <
typename Container>
2364 using T =
typename Container::value_type;
2366 std::vector<std::pair<T, size_t>> result;
2367 const size_t size = stl_detail::safe_size(c);
2370 if constexpr (!stl_detail::is_std_hashable_v<T>)
2373 for (
const auto & item : c)
2375 auto it = std::find_if(result.begin(), result.end(),
2376 [&item](
const auto & p) { return p.first == item; });
2377 if (it != result.end())
2380 result.emplace_back(item, 1);
2383 else if (
size <= stl_detail::ADAPTIVE_THRESHOLD)
2386 for (
const auto & item : c)
2388 auto it = std::find_if(result.begin(), result.end(),
2389 [&item](
const auto & p) { return p.first == item; });
2390 if (it != result.end())
2393 result.emplace_back(item, 1);
2399 std::unordered_map<T, size_t> counts;
2400 counts.reserve(
size);
2401 std::vector<T> order;
2402 order.reserve(
size);
2404 for (
const auto & item : c)
2406 auto [it, inserted] = counts.try_emplace(item, 0);
2409 order.push_back(item);
2412 result.reserve(order.size());
2413 for (
const auto & item : order)
2414 result.emplace_back(item, counts[item]);
2430 template <
typename Pred,
typename Container>
2433 using T =
typename Container::value_type;
2435 std::vector<T> result;
2436 auto & pred_ref =
pred;
2437 for (
const auto & item: c)
2438 if (not pred_ref(item))
2439 result.push_back(item);
C++20 Ranges support and adaptors for Aleph-w containers.
T & insert(const T &item)
Insert a new item by copy.
void empty() noexcept
empty the list
size_t size() const noexcept
Count the number of elements of the list.
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Freq_Node * pred
Predecessor node in level-order traversal.
constexpr T ranges_fold_left(Container &&c, T init, BinaryOp &&op)
Fallback fold_left using range-based for loop.
bool ranges_any_of(const Container &c, Pred &&pred)
Fallback any_of using range-based for loop.
bool ranges_all_of(const Container &c, Pred &&pred)
Fallback all_of using range-based for loop.
bool arrangements_impl(const std::vector< T > &arr, size_t k, std::vector< T > ¤t, std::vector< bool > &used, Op &op_ref)
bool permutations_impl(std::vector< T > &arr, size_t start, Op &op_ref)
bool combinations_impl(const std::vector< T > &arr, size_t k, size_t start, std::vector< T > ¤t, Op &op_ref)
constexpr size_t ADAPTIVE_THRESHOLD
Threshold for switching from linear to hash-based algorithms.
constexpr bool is_std_hashable_v
void try_reserve_n(Result &result, size_t n)
Helper to reserve with a specific size if the result supports it.
size_t safe_size(const Container &c)
Helper to get container size safely (returns 0 for containers without size())
void try_reserve(Result &result, const Container &c)
Helper to reserve if possible.
constexpr bool has_reverse_iterators_v
constexpr bool has_size_v
Main namespace for Aleph-w library functions.
auto stl_first(const Container &c)
Get first element.
T stl_reduce(T init, Op &&op, const Container &c)
Alias for stl_foldl.
std::vector< T > stl_scan_left(T init, Op &&op, const Container &c)
Scan left - fold with all intermediate results.
bool stl_any(Pred &&pred, const Container &c)
Alias for stl_exists.
auto stl_span(Pred &&pred, const Container &c)
Split at predicate boundary (span in Haskell).
auto stl_take_last(size_t n, const Container &c)
Take last n elements.
bool all(Container &container, Operation &operation)
Return true if all elements satisfy a predicate.
auto stl_chunks(size_t n, const Container &c)
Split container into chunks of size n (each_slice in Ruby).
int stl_compare(const Container1 &c1, const Container2 &c2)
Compare two containers lexicographically.
auto stl_min_max(const Container &c)
Get both min and max in a single pass.
auto stl_last(const Container &c)
Get last element.
bool stl_traverse_arrangements(size_t k, Op &&op, const Container &c)
Traverse all k-arrangements (k-permutations) of a container.
auto stl_distinct(const Container &c)
Remove all duplicates (keeps first occurrence).
auto stl_max(const Container &c)
Get maximum element.
size_t size(Node *root) noexcept
auto stl_flatten(const Container &c)
Flatten a container of containers.
auto stl_reject(Pred &&pred, const Container &c)
Filter out elements (reject in Ruby, opposite of filter).
auto stl_filter(Pred &&pred, const Container &c)
Filter elements satisfying predicate.
auto stl_arrangements(size_t k, const Container &c)
Generate all k-arrangements (k-permutations) of a container.
auto stl_drop(size_t n, const Container &c)
Drop first n elements, return the rest.
auto stl_enumerate_to_pairs(const Container &c)
Enumerate container (return pairs of index and element).
bool stl_equal(const Container1 &c1, const Container2 &c2)
Check equality of two containers.
auto stl_concat(const Container1 &c1, const Container2 &c2)
Concatenate two containers.
auto stl_combinations(size_t k, const Container &c)
Generate all k-combinations of a container.
auto stl_take_while(Pred &&pred, const Container &c)
Take elements while predicate is true.
auto stl_find_mapi(Op &&op, const Container &c)
Find and map with index (find_mapi in ML).
auto stl_nth(const size_t n, const Container &c)
Get n-th element.
auto stl_map(Op &&op, const Container &c)
Map operation - transform each element.
bool stl_mem(const T &target, const Container &c)
Check if element exists in container (mem in ML).
std::optional< size_t > stl_find_index(Pred &&pred, const Container &c)
Find index of first element satisfying predicate.
T stl_foldl(T init, Op &&op, const Container &c)
Left fold (foldl) - reduce from left to right.
auto stl_min_by(Key &&key, const Container &c)
Get minimum element by key function.
std::vector< T > stl_linspace(T start, T end, size_t n)
Generate n evenly spaced values between start and end.
bool stl_exists(Pred &&pred, const Container &c)
Check if any element satisfies predicate.
std::decay_t< typename HeadC::Item_Type > T
auto stl_take(size_t n, const Container &c)
Take first n elements.
auto stl_generate(size_t n, Gen &&gen)
Generate a vector using a generator function.
std::vector< T > stl_range(T start, T end, T step=1)
Generate a range of values [start, end] with given step.
auto stl_init(const Container &c)
Get all elements except the last (init in Haskell).
bool stl_traverse_permutations(Op &&op, const Container &c)
Traverse all permutations of a container.
size_t stl_count_value(const T &target, const Container &c)
Count occurrences of a value.
auto stl_sort(const Container &c)
Return sorted copy of container.
auto stl_permutations(const Container &c)
Generate all permutations of a container.
auto stl_tally(const Container &c)
Count occurrences of each element (tally in Ruby, frequencies).
bool stl_all(Pred &&pred, const Container &c)
Check if all elements satisfy predicate.
auto stl_partition(Pred &&pred, const Container &c)
Partition elements by predicate.
auto stl_unique(const Container &c)
Remove consecutive duplicates.
auto stl_mapi(Op &&op, const Container &c)
Map with index (mapi in ML).
size_t stl_count(Pred &&pred, const Container &c)
Count elements satisfying predicate.
void stl_for_each_indexed(Op &&op, const Container &c)
Apply operation to each element with index.
auto stl_sum(const Container &c)
Sum all elements.
auto stl_sliding_window(size_t n, const Container &c)
Sliding window of size n over container (each_cons in Ruby).
auto stl_max_by(Key &&key, const Container &c)
Get maximum element by key function.
auto stl_group_by(Key &&key, const Container &c)
Group elements by key function.
auto stl_min(const Container &c)
Get minimum element.
bool stl_none(Pred &&pred, const Container &c)
Check if no element satisfies predicate.
auto stl_reverse(const Container &c)
Return reversed copy of container.
auto stl_flat_map(Op &&op, const Container &c)
Flat map - map then flatten.
std::vector< T > stl_rep(size_t n, const T &value)
Generate a vector of n repeated values.
bool stl_traverse_combinations(size_t k, Op &&op, const Container &c)
Traverse all k-combinations of a container.
T stl_foldr(T init, Op &&op, const Container &c)
Right fold (foldr) - reduce from right to left.
std::vector< T > stl_scan_right(T init, Op &&op, const Container &c)
Scan right - right fold with all intermediate results.
auto stl_unzip_pairs(const Container &c)
Unzip pairs into two vectors.
auto stl_drop_while(Pred &&pred, const Container &c)
Drop elements while predicate is true, return the rest.
auto stl_intersperse(const T &sep, const Container &c)
Insert element between each pair (intersperse in Haskell).
auto stl_cartesian_product(const std::vector< std::vector< T > > &containers)
Generate cartesian product of multiple containers.
auto stl_product(const Container &c)
Product of all elements.
auto stl_tail(const Container &c)
Get all elements except the first (tail in Haskell).
auto stl_filteri(Pred &&pred, const Container &c)
Filter with index (filteri in ML).
auto stl_find(Pred &&pred, const Container &c)
Find first element satisfying predicate.
void stl_for_each(Op &&op, const Container &c)
Apply operation to each element (for_each).
auto stl_split_at(size_t n, const Container &c)
Split at position n, returning (take n, drop n) in one pass.
auto stl_sort_by(Cmp &&cmp, const Container &c)
Return sorted copy using custom comparator.
auto stl_power_set(const Container &c)
Generate power set (all subsets) of a container.
auto stl_group(const Container &c)
Group consecutive equal elements.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
auto stl_zip_to_pairs(const Container1 &c1, const Container2 &c2)
Zip two containers into pairs.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
auto stl_find_last(Pred &&pred, const Container &c)
Find last element satisfying predicate.
Detect if a container has reverse iterators.
Detect if a type has a size() method.
Detect if a type is hashable via std::hash.