32# ifndef AH_UNI_FUNCTIONAL_H
33# define AH_UNI_FUNCTIONAL_H
71# include <type_traits>
86 namespace uni_functional_detail
89 template <
typename T,
typename =
void>
95 decltype(std::declval<const T &>().begin()),
96 decltype(std::declval<const T &>().end()),
97 typename T::value_type
102 template <
typename T,
typename =
void>
106 template <
typename T>
108 typename T::Iterator,
109 typename T::Item_Type,
110 decltype(std::declval<typename T::Iterator>().has_curr()),
111 decltype(std::declval<typename T::Iterator>().get_curr()),
112 decltype(std::declval<typename T::Iterator>().next())
117 template <
typename T,
typename =
void>
121 template <
typename T>
123 decltype(std::declval<const T &>().rbegin()),
124 decltype(std::declval<const T &>().rend())
129 template <
typename T,
typename =
void>
132 template <
typename T>
135 using type =
typename T::value_type;
138 template <
typename T>
140 has_aleph_iterator<T>::value and not has_stl_iterator<T>::value>>
142 using type = std::decay_t<typename T::Item_Type>;
145 template <
typename T>
149 template <
typename T>
153 template <
typename T>
173 template <
typename Op,
typename Container>
177 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
178 for (
const auto & item: c)
181 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
193 template <
typename Op,
typename Container>
198 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
199 for (
const auto & item: c)
202 for (
auto it = c.get_it(); it.has_curr(); it.next_ne(), ++i)
215 template <
typename Op,
typename Container>
219 using R = std::decay_t<decltype(std::forward<Op>(op)(std::declval<T>()))>;
221 std::vector<R> result;
224 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
226 result.reserve(c.size());
227 for (
const auto & item: c)
228 result.push_back(
op_ref(item));
231 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
232 result.push_back(
op_ref(it.get_curr()));
246 template <
typename Op,
typename Container>
250 using R = std::decay_t<decltype(std::forward<Op>(op)(
size_t{}, std::declval<T>()))>;
252 std::vector<R> result;
256 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
258 result.reserve(c.size());
259 for (
const auto & item: c)
260 result.push_back(
op_ref(i++, item));
263 for (
auto it = c.get_it(); it.has_curr(); it.next_ne(), ++i)
264 result.push_back(
op_ref(i, it.get_curr()));
278 template <
typename Pred,
typename Container>
283 std::vector<T> result;
286 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
288 for (
const auto & item: c)
290 result.push_back(item);
294 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
295 if (
const auto & item = it.get_curr();
pred_ref(item))
296 result.push_back(item);
310 template <
typename Pred,
typename Container>
315 std::vector<T> result;
319 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
320 for (
const auto & item: c)
323 result.push_back(item);
327 for (
auto it = c.get_it(); it.has_curr(); it.next_ne(), ++i)
328 if (
const auto & item = it.get_curr();
pred_ref(i, item))
329 result.push_back(item);
344 template <
typename T,
typename Op,
typename Container>
350 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
351 for (
const auto & item: c)
354 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
360 template <
typename T,
typename Op,
typename Container>
376 template <
typename T,
typename Op,
typename Container>
379 std::vector<T> result;
380 result.push_back(
init);
385 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
386 for (
const auto & item: c)
389 result.push_back(
acc);
392 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
395 result.push_back(
acc);
413 template <
typename Pred,
typename Container>
417 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
419 for (
const auto & item: c)
425 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
441 template <
typename Pred,
typename Container>
445 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
447 for (
const auto & item: c)
453 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
461 template <
typename Pred,
typename Container>
472 template <
typename Pred,
typename Container>
491 template <
typename Pred,
typename Container>
497 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
499 for (
const auto & item: c)
501 return std::optional<T>(item);
505 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
506 if (
const auto & item = it.get_curr();
pred_ref(item))
507 return std::optional<T>(item);
509 return std::optional<T>{};
521 template <
typename Pred,
typename Container>
527 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
529 for (
const auto & item: c)
538 for (
auto it = c.get_it(); it.has_curr(); it.next_ne(), ++i)
554 template <
typename Op,
typename Container>
558 using OptType = std::decay_t<decltype(std::forward<Op>(op)(
size_t{}, std::declval<T>()))>;
563 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
565 for (
const auto & item: c)
566 if (
auto result =
op_ref(i++, item))
571 for (
auto it = c.get_it(); it.has_curr(); it.next_ne(), ++i)
572 if (
auto result =
op_ref(i, it.get_curr()))
587 template <
typename T,
typename Container>
590 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
592 for (
const auto & item: c)
598 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
599 if (it.get_curr() ==
target)
618 template <
typename Pred,
typename Container>
624 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
626 for (
const auto & item: c)
632 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
647 template <
typename Container>
650 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
657 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
676 template <
typename Container>
681 std::vector<T> result;
685 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
687 for (
const auto & item: c)
689 if (
count >= n)
break;
690 result.push_back(item);
696 for (
auto it = c.get_it(); it.has_curr()
and count < n; it.next_ne(), ++
count)
697 result.push_back(it.get_curr());
711 template <
typename Container>
716 std::vector<T> result;
719 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
721 for (
const auto & item: c)
724 result.push_back(item);
730 for (
auto it = c.get_it(); it.has_curr(); it.next_ne(), ++
count)
732 result.push_back(it.get_curr());
746 template <
typename Pred,
typename Container>
751 std::vector<T> result;
754 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
756 for (
const auto & item: c)
760 result.push_back(item);
765 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
767 const auto & item = it.get_curr();
770 result.push_back(item);
785 template <
typename Pred,
typename Container>
790 std::vector<T> result;
794 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
796 for (
const auto & item: c)
801 result.push_back(item);
806 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
808 const auto & item = it.get_curr();
812 result.push_back(item);
830 template <
typename Container>
835 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
839 return std::optional<T>{};
840 return std::optional<T>(*it);
844 auto it = c.get_it();
845 if (
not it.has_curr())
846 return std::optional<T>{};
847 return std::optional<T>(it.get_curr());
859 template <
typename Container>
864 std::optional<T> result;
866 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
868 for (
const auto & item: c)
873 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
874 result = it.get_curr();
888 template <
typename Container>
895 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
897 for (
const auto & item: c)
900 return std::optional<T>(item);
906 for (
auto it = c.get_it(); it.has_curr(); it.next_ne(), ++i)
908 return std::optional<T>(it.get_curr());
910 return std::optional<T>{};
925 template <
typename Container>
930 std::optional<T> result;
932 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
940 for (; it != c.end(); ++it)
943 return std::optional<T>(
min_val);
947 auto it = c.get_it();
948 if (
not it.has_curr())
953 for (; it.has_curr(); it.next_ne())
955 const auto & item = it.get_curr();
959 return std::optional<T>(
min_val);
971 template <
typename Container>
976 std::optional<T> result;
978 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
986 for (; it != c.end(); ++it)
989 return std::optional<T>(
max_val);
993 auto it = c.get_it();
994 if (
not it.has_curr())
999 for (; it.has_curr(); it.next_ne())
1001 const auto & item = it.get_curr();
1005 return std::optional<T>(
max_val);
1017 template <
typename Container>
1021 using ResultType = std::optional<std::pair<T, T>>;
1023 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1025 auto it = c.begin();
1033 for (; it != c.end(); ++it)
1042 auto it = c.get_it();
1043 if (
not it.has_curr())
1050 for (; it.has_curr(); it.next_ne())
1052 const auto & item = it.get_curr();
1072 template <
typename Container>
1078 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1080 for (
const auto & item: c)
1085 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1086 sum =
sum + it.get_curr();
1099 template <
typename Container>
1104 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1106 auto it = c.begin();
1107 if (it == c.end())
return T{};
1111 for (; it != c.end(); ++it)
1117 auto it = c.get_it();
1118 if (
not it.has_curr())
return T{};
1120 T prod = it.get_curr();
1122 for (; it.has_curr(); it.next_ne())
1141 template <
typename Pred,
typename Container>
1149 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1151 for (
const auto & item: c)
1161 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1163 const auto & item = it.get_curr();
1186 template <
typename Container1,
typename Container2>
1191 std::vector<T> result;
1193 if constexpr (uni_functional_detail::is_stl_container_v<Container1>)
1194 for (
const auto & item:
c1)
1195 result.push_back(item);
1197 for (
auto it =
c1.
get_it(); it.has_curr(); it.next_ne())
1198 result.push_back(it.get_curr());
1200 if constexpr (uni_functional_detail::is_stl_container_v<Container2>)
1201 for (
const auto & item:
c2)
1202 result.push_back(item);
1204 for (
auto it =
c2.
get_it(); it.has_curr(); it.next_ne())
1205 result.push_back(it.get_curr());
1218 template <
typename Container>
1224 std::vector<T> result;
1226 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1228 for (
const auto &
inner: c)
1230 if constexpr (uni_functional_detail::is_stl_container_v<InnerContainer>)
1231 for (
const auto & item:
inner)
1232 result.push_back(item);
1234 for (
auto it =
inner.
get_it(); it.has_curr(); it.next_ne())
1235 result.push_back(it.get_curr());
1240 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1242 const auto &
inner = it.get_curr();
1243 if constexpr (uni_functional_detail::is_stl_container_v<InnerContainer>)
1244 for (
const auto & item:
inner)
1245 result.push_back(item);
1247 for (
auto it2 =
inner.
get_it(); it2.has_curr(); it2.next_ne())
1248 result.push_back(it2.get_curr());
1264 template <
typename Op,
typename Container>
1268 using InnerContainer = std::decay_t<decltype(std::forward<Op>(op)(std::declval<T>()))>;
1271 std::vector<R> result;
1274 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1276 for (
const auto & item: c)
1279 if constexpr (uni_functional_detail::is_stl_container_v<InnerContainer>)
1283 for (
auto it =
inner.
get_it(); it.has_curr(); it.next_ne())
1284 result.push_back(it.get_curr());
1289 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1292 if constexpr (uni_functional_detail::is_stl_container_v<InnerContainer>)
1296 for (
auto it2 =
inner.
get_it(); it2.has_curr(); it2.next_ne())
1297 result.push_back(it2.get_curr());
1319 template <
typename Container>
1324 std::vector<T> result;
1326 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1328 for (
const auto & item: c)
1329 if (std::find(result.begin(), result.end(), item) == result.end())
1330 result.push_back(item);
1334 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1335 if (
const auto & item = it.get_curr(); std::find(result.begin(), result.end(), item) == result.end())
1336 result.push_back(item);
1351 template <
typename Key,
typename Container>
1355 using K = std::decay_t<decltype(std::forward<Key>(key)(std::declval<T>()))>;
1357 std::vector<std::pair<K, std::vector<T>>> result;
1360 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1362 for (
const auto & item: c)
1365 auto it = std::find_if(result.begin(), result.end(),
1366 [&
k](
const auto & p) { return p.first == k; });
1367 if (it != result.end())
1368 it->second.push_back(item);
1370 result.emplace_back(std::move(
k), std::vector<T>{item});
1375 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1377 const auto & item = it.get_curr();
1379 auto res_it = std::find_if(result.begin(), result.end(),
1380 [&
k](
const auto & p) { return p.first == k; });
1382 res_it->second.push_back(item);
1384 result.emplace_back(std::move(
k), std::vector<T>{item});
1399 template <
typename Container>
1404 std::vector<std::pair<T, size_t>> result;
1406 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1408 for (
const auto & item: c)
1410 auto it = std::find_if(result.begin(), result.end(),
1411 [&item](
const auto & p) { return p.first == item; });
1412 if (it != result.end())
1415 result.emplace_back(item, 1);
1420 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1422 const auto & item = it.get_curr();
1423 auto res_it = std::find_if(result.begin(), result.end(),
1424 [&item](
const auto & p) { return p.first == item; });
1428 result.emplace_back(item, 1);
1447 template <
typename Container>
1452 std::vector<T> result;
1454 if constexpr (uni_functional_detail::is_stl_container_v<Container>)
1456 result.reserve(c.size());
1457 for (
const auto & item: c)
1458 result.push_back(item);
1462 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1463 result.push_back(it.get_curr());
1484 template <
typename Container1,
typename Container2>
1487 constexpr bool c1_is_stl = uni_functional_detail::is_stl_container_v<Container1>;
1488 constexpr bool c2_is_stl = uni_functional_detail::is_stl_container_v<Container2>;
1496 if (
not (*it1 == *it2))
1505 for (; it1 !=
c1.
end()
and it2.has_curr(); ++it1, it2.next_ne())
1506 if (
not (*it1 == it2.get_curr()))
1515 for (; it1.has_curr()
and it2 !=
c2.
end(); it1.next_ne(), ++it2)
1516 if (
not (it1.get_curr() == *it2))
1525 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1526 if (
not (it1.get_curr() == it2.get_curr()))
1528 return not it1.has_curr()
and not it2.has_curr();
1544 template <
typename Container1,
typename Container2>
1547 constexpr bool c1_is_stl = uni_functional_detail::is_stl_container_v<Container1>;
1548 constexpr bool c2_is_stl = uni_functional_detail::is_stl_container_v<Container2>;
1557 if (*it1 < *it2)
return -1;
1558 if (*it2 < *it1)
return 1;
1561 return (it1 ==
c1.
end()) ? -1 : 1;
1568 for (; it1 !=
c1.
end()
and it2.has_curr(); ++it1, it2.next_ne())
1570 if (*it1 < it2.get_curr())
return -1;
1571 if (it2.get_curr() < *it1)
return 1;
1573 if (it1 ==
c1.
end()
and not it2.has_curr())
return 0;
1574 return (it1 ==
c1.
end()) ? -1 : 1;
1581 for (; it1.has_curr()
and it2 !=
c2.
end(); it1.next_ne(), ++it2)
1583 if (it1.get_curr() < *it2)
return -1;
1584 if (*it2 < it1.get_curr())
return 1;
1586 if (
not it1.has_curr()
and it2 ==
c2.
end())
return 0;
1587 return (
not it1.has_curr()) ? -1 : 1;
1594 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1596 if (it1.get_curr() < it2.get_curr())
return -1;
1597 if (it2.get_curr() < it1.get_curr())
return 1;
1599 if (
not it1.has_curr()
and not it2.has_curr())
return 0;
1600 return (
not it1.has_curr()) ? -1 : 1;
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
Freq_Node * pred
Predecessor node in level-order traversal.
constexpr bool is_stl_container_v
constexpr bool is_aleph_only_v
typename container_value_type< std::decay_t< T > >::type value_t
Main namespace for Aleph-w library functions.
T uni_reduce(T init, Op &&op, const Container &c)
Alias for uni_foldl.
auto uni_distinct(const Container &c)
Remove all duplicates (keeps first occurrence).
bool uni_none(Pred &&pred, const Container &c)
Check if no element satisfies predicate.
auto uni_filter(Pred &&pred, const Container &c)
Filter elements satisfying predicate.
auto uni_nth(size_t n, const Container &c)
Get n-th element.
int uni_compare(const Container1 &c1, const Container2 &c2)
Compare two containers lexicographically.
bool uni_equal(const Container1 &c1, const Container2 &c2)
Check equality of two containers.
std::vector< T > uni_scan_left(T init, Op &&op, const Container &c)
Scan left - fold with all intermediate results.
size_t uni_length(const Container &c)
Get container length.
auto uni_tally(const Container &c)
Count occurrences of each element (frequency count).
auto uni_flatten(const Container &c)
Flatten a container of containers.
auto uni_flat_map(Op &&op, const Container &c)
Flat map - map then flatten.
auto uni_drop_while(Pred &&pred, const Container &c)
Drop elements while predicate is true, return the rest.
std::decay_t< typename HeadC::Item_Type > T
auto uni_product(const Container &c)
Product of all elements.
auto uni_find(Pred &&pred, const Container &c)
Find first element satisfying predicate.
bool uni_mem(const T &target, const Container &c)
Check if element exists in container (mem in ML).
auto uni_group_by(Key &&key, const Container &c)
Group elements by key function.
auto uni_filteri(Pred &&pred, const Container &c)
Filter with index (filteri in ML).
auto uni_map(Op &&op, const Container &c)
Map operation - transform each element.
auto uni_concat(const Container1 &c1, const Container2 &c2)
Concatenate two containers.
auto uni_last(const Container &c)
Get last element.
auto uni_min_max(const Container &c)
Get both min and max in a single pass.
auto uni_min(const Container &c)
Get minimum element.
size_t uni_count(Pred &&pred, const Container &c)
Count elements satisfying predicate.
void uni_for_each_indexed(Op &&op, const Container &c)
Apply operation to each element with index.
T uni_foldl(T init, Op &&op, const Container &c)
Left fold (foldl) - reduce from left to right.
auto uni_drop(size_t n, const Container &c)
Drop first n elements, return the rest.
auto uni_max(const Container &c)
Get maximum element.
void uni_for_each(Op &&op, const Container &c)
Apply operation to each element (for_each).
auto uni_find_mapi(Op &&op, const Container &c)
Find and map with index (find_mapi in ML).
auto uni_take_while(Pred &&pred, const Container &c)
Take elements while predicate is true.
bool uni_all(Pred &&pred, const Container &c)
Check if all elements satisfy predicate.
auto uni_first(const Container &c)
Get first element.
auto uni_partition(Pred &&pred, const Container &c)
Partition elements by predicate.
auto uni_to_vector(const Container &c)
Convert container to std::vector.
auto uni_mapi(Op &&op, const Container &c)
Map with index (mapi in ML).
bool uni_any(Pred &&pred, const Container &c)
Alias for uni_exists.
auto uni_take(size_t n, const Container &c)
Take first n elements.
auto uni_sum(const Container &c)
Sum all elements.
bool uni_exists(Pred &&pred, const Container &c)
Check if any element satisfies predicate.
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.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
std::optional< size_t > uni_find_index(Pred &&pred, const Container &c)
Find index of first element satisfying predicate.
typename T::value_type type
std::decay_t< typename T::Item_Type > type