sequence.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*=============================================================================
  2. Copyright (c) 2017 Paul Fultz II
  3. sequence.cpp
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. /*=============================================================================
  8. Copyright (c) 2016 Paul Fultz II
  9. print.cpp
  10. Distributed under the Boost Software License, Version 1.0. (See accompanying
  11. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  12. ==============================================================================*/
  13. #include "example.h"
  14. #include <tuple>
  15. using namespace boost::hof;
  16. // Transform each element of a tuple by calling f
  17. BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_transform) = [](auto&& sequence, auto f)
  18. {
  19. return unpack(proj(f, construct<std::tuple>()))(std::forward<decltype(sequence)>(sequence));
  20. };
  21. // Call f on each element of tuple
  22. BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_for_each) = [](auto&& sequence, auto f)
  23. {
  24. return unpack(proj(f))(std::forward<decltype(sequence)>(sequence));
  25. };
  26. // Fold over tuple using a f as the binary operator
  27. BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_fold) = [](auto&& sequence, auto f)
  28. {
  29. return unpack(fold(f))(std::forward<decltype(sequence)>(sequence));
  30. };
  31. // Concat multiple tuples
  32. BOOST_HOF_STATIC_FUNCTION(tuple_cat) = unpack(construct<std::tuple>());
  33. // Join a tuple of tuples into just a tuple
  34. BOOST_HOF_STATIC_FUNCTION(tuple_join) = unpack(tuple_cat);
  35. // Filter elements in a tuple using a predicate
  36. BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_filter) = [](auto&& sequence, auto predicate)
  37. {
  38. return compose(tuple_join, tuple_transform)(
  39. std::forward<decltype(sequence)>(sequence),
  40. [&](auto&& x)
  41. {
  42. return first_of(
  43. if_(predicate(std::forward<decltype(x)>(x)))(pack),
  44. always(pack())
  45. )(std::forward<decltype(x)>(x));
  46. }
  47. );
  48. };
  49. // Zip two tuples together
  50. BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_zip_with) = [](auto&& sequence1, auto&& sequence2, auto f)
  51. {
  52. auto&& functions = tuple_transform(
  53. std::forward<decltype(sequence1)>(sequence1),
  54. [&](auto&& x)
  55. {
  56. return [&](auto&& y)
  57. {
  58. return f(std::forward<decltype(x)>(x), std::forward<decltype(y)>(y));
  59. };
  60. }
  61. );
  62. auto combined = unpack(capture(construct<std::tuple>())(combine))(functions);
  63. return unpack(combined)(std::forward<decltype(sequence2)>(sequence2));
  64. };
  65. // Dot product of a tuple
  66. BOOST_HOF_STATIC_LAMBDA_FUNCTION(tuple_dot) = [](auto&& a, auto&& b)
  67. {
  68. auto product = tuple_zip_with(a, b, [](auto x, auto y) { return x*y; });
  69. return tuple_fold(product, [](auto x, auto y) { return x+y; });
  70. };
  71. void run_each()
  72. {
  73. auto t = std::make_tuple(1, 2);
  74. tuple_for_each(t, [](int i) { std::cout << i << std::endl; });
  75. }
  76. void run_transform()
  77. {
  78. auto t = std::make_tuple(1, 2);
  79. auto r = tuple_transform(t, [](int i) { return i*i; });
  80. assert(r == std::make_tuple(1, 4));
  81. (void)r;
  82. }
  83. void run_filter()
  84. {
  85. auto t = std::make_tuple(1, 2, 'x', 3);
  86. auto r = tuple_filter(t, [](auto x) { return std::is_same<int, decltype(x)>(); });
  87. assert(r == std::make_tuple(1, 2, 3));
  88. (void)r;
  89. }
  90. void run_zip()
  91. {
  92. auto t1 = std::make_tuple(1, 2);
  93. auto t2 = std::make_tuple(3, 4);
  94. auto p = tuple_zip_with(t1, t2, [](auto x, auto y) { return x*y; });
  95. int r = tuple_fold(p, [](auto x, auto y) { return x+y; });
  96. assert(r == (1*3 + 4*2));
  97. (void)r;
  98. }
  99. void run_dot()
  100. {
  101. auto t1 = std::make_tuple(1, 2);
  102. auto t2 = std::make_tuple(3, 4);
  103. int r = tuple_dot(t1, t2);
  104. assert(r == (1*3 + 4*2));
  105. (void)r;
  106. }
  107. int main()
  108. {
  109. run_transform();
  110. run_filter();
  111. run_zip();
  112. }