1 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
2 // https://github.com/Dobiasd/FunctionalPlus
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #include <doctest/doctest.h>
8 #include <fplus/fplus.hpp>
9 #include <vector>
10
11 namespace {
is_odd_int(int x)12 bool is_odd_int(int x) { return x % 2 != 0; }
13 }
14
15 TEST_CASE("readme_examples_test - KeepIf")
16 {
17 typedef std::vector<int> Ints;
18 Ints values = { 24, 11, 65, 44, 80, 18, 73, 90, 69, 18 };
19
20 { // Version 1: hand written range based for loop
21 Ints odds;
22 for (int x : values)
23 if (is_odd_int(x))
24 odds.push_back(x);
25 }
26
27 { // Version 2: STL
28 Ints odds;
29 std::copy_if(std::begin(values), std::end(values),
30 std::back_inserter(odds), is_odd_int);
31 }
32
33 { // Version : FunctionalPlus
34 auto odds = fplus::keep_if(is_odd_int, values);
35 }
36 }
37
38 TEST_CASE("readme_examples_test - SameOldSameOld")
39 {
40 std::list<std::string> things = {"same old", "same old"};
41 REQUIRE(fplus::all_the_same(things));
42 }
43
44 TEST_CASE("readme_examples_test - eIInTeam")
45 {
46 std::string team = "Our team is great. I love everybody I work with.";
47 REQUIRE_EQ(fplus::count("I", fplus::split_words(false, team)), 2);
48 }
49
50 namespace {
51 struct Entity
52 {
Entity__anon63f9b6010211::Entity53 Entity() : calm_(true), bright_(true) {}
54 bool calm_;
55 bool bright_;
56 };
57 }
58
59 TEST_CASE("readme_examples_test - AllIsCalmAndBright")
60 {
__anon63f9b6010302(const Entity& e) 61 auto isCalm = [](const Entity& e) { return e.calm_; };
__anon63f9b6010402(const Entity& e) 62 auto isBright = [](const Entity& e) { return e.bright_; };
63 std::vector<Entity> entities(4);
64 REQUIRE(fplus::all_by(fplus::logical_and(isCalm, isBright), entities));
65 }
66
67 namespace {
68 struct cat
69 {
cuteness__anon63f9b6010511::cat70 double cuteness() const
71 {
72 return softness_ * temperature_ * roundness_ * fur_amount_ - size_;
73 }
74 std::string name_;
75 double softness_;
76 double temperature_;
77 double size_;
78 double roundness_;
79 double fur_amount_;
80 };
81 }
82
83 TEST_CASE("readme_examples_test - TheCutestCat")
84 {
85 std::vector<cat> cats = {
86 {"Tigger", 5, 5, 5, 5, 5},
87 {"Simba", 2, 9, 9, 2, 7},
88 {"Muffin", 9, 4, 2, 8, 6},
89 {"Garfield", 6, 5, 7, 9, 5}};
90
91 auto cutest_cat = fplus::maximum_on(std::mem_fn(&cat::cuteness), cats);
92 REQUIRE_EQ(cutest_cat.name_, std::string("Muffin"));
93 }
94
95 namespace {
collatz_seq(int x)96 std::list<int> collatz_seq(int x)
97 {
98 std::list<int> result;
99 while (x > 1)
100 {
101 result.push_back(x);
102 if (x % 2 == 0)
103 x = x / 2;
104 else
105 x = 3 * x + 1;
106 }
107 result.push_back(x);
108 return result;
109 }
110 }
111
112 TEST_CASE("readme_examples_test - CollatzSequence")
113 {
114 typedef std::list<int> Ints;
115
116 // [1, 2, 3 ... 29]
117 auto xs = fplus::numbers<int>(1, 30);
118
119 // A function that does [1, 2, 3, 4, 5] -> "[1 => 2 => 3 => 4 => 5]"
120 auto show_ints = fplus::bind_1st_of_2(fplus::show_cont_with<Ints>, " => ");
121
122 // A composed function that calculates a Collatz sequence and shows it.
123 auto show_collats_seq = fplus::compose(collatz_seq, show_ints);
124
125 // Associate the numbers with the string representation of their sequences.
126 auto collatz_dict = fplus::create_map_with(show_collats_seq, xs);
127
128 // Print some of the sequences.
129 REQUIRE_EQ(collatz_dict[13], std::string("[13 => 40 => 20 => 10 => 5 => 16 => 8 => 4 => 2 => 1]"));
130 REQUIRE_EQ(collatz_dict[17], std::string("[17 => 52 => 26 => 13 => 40 => 20 => 10 => 5 => 16 => 8 => 4 => 2 => 1]"));
131 }
132
133 namespace {
gemstone_count(const std::string & input)134 std::string gemstone_count(const std::string& input)
135 {
136 using namespace fplus;
137
138 typedef std::set<std::string::value_type> characters;
139
140 const auto lines = split_lines(false, input);
141
142 const auto sets = transform(
143 convert_container<characters, std::string>,
144 lines);
145
146 const auto gem_elements = fold_left_1(
147 set_intersection<characters>, sets);
148
149 return show(size_of_cont(gem_elements));
150 }
151
gemstone_count_fwd_apply(const std::string & input)152 std::string gemstone_count_fwd_apply(const std::string& input)
153 {
154 using namespace fplus;
155 typedef std::set<std::string::value_type> characters;
156 return fwd::apply(
157 input
158 , fwd::split_lines(false)
159 , fwd::transform(convert_container<characters, std::string>)
160 , fwd::fold_left_1(set_intersection<characters>)
161 , fwd::size_of_cont()
162 , fwd::show()
163 );
164 }
165
166 typedef std::set<std::string::value_type> characters;
167 const auto gemstone_count_fwd_compose = fplus::fwd::compose(
168 fplus::fwd::split_lines(false),
169 fplus::fwd::transform(fplus::convert_container<characters, std::string>),
170 fplus::fwd::fold_left_1(fplus::set_intersection<characters>),
171 fplus::fwd::size_of_cont(),
172 fplus::fwd::show()
173 );
174 }
175
176 TEST_CASE("readme_examples_test - fwd_style")
177 {
178 const std::string input =
179 "Lorem ipsum\ndolor sit amet,\nconsectetur,\nadipisci velit";
180 const auto result = gemstone_count(input);
181 const auto result_fwd_apply = gemstone_count_fwd_apply(input);
182 const auto result_fwd_compose = gemstone_count_fwd_compose(input);
183 REQUIRE_EQ(result, std::string("2"));
184 REQUIRE_EQ(result_fwd_apply, std::string("2"));
185 REQUIRE_EQ(result_fwd_compose, std::string("2"));
186 }
187
188 namespace {
square_is_even(const std::vector<int> & xs)189 std::string square_is_even(const std::vector<int>& xs)
190 {
191 using namespace fplus;
192 auto ys = fplus::transform(fplus::square<int>, xs);
193 auto zs = fplus::keep_if(fplus::is_even<int>, ys);
194 return show(size_of_cont(zs));
195 }
196
square_is_even_chain(const std::vector<int> & xs)197 std::string square_is_even_chain(const std::vector<int>& xs)
198 {
199 using namespace fplus;
200 auto zs = fplus::keep_if(fplus::is_even<int>, fplus::transform(fplus::square<int>, xs));
201 return show(size_of_cont(zs));
202 }
203
square_is_even_fwd_apply(const std::vector<int> & xs)204 std::string square_is_even_fwd_apply(const std::vector<int>& xs)
205 {
206 using namespace fplus;
207 auto zs = fwd::apply(
208 xs
209 , fplus::fwd::transform(fplus::square<int>)
210 , fplus::fwd::keep_if(fplus::is_even<int>));
211 return show(size_of_cont(zs));
212 }
213
214 const auto square_is_even_fwd_compose = fplus::fwd::compose(
215 fplus::fwd::transform(fplus::square<int>),
216 fplus::fwd::keep_if(fplus::is_even<int>),
217 fplus::fwd::size_of_cont(),
218 fplus::fwd::show()
219 );
220 }
221
222 TEST_CASE("readme_examples_test - square_is_even")
223 {
224 const std::vector<int> xs = {0,1,2,3,4,5,6,7};
225 const auto result = square_is_even(xs); // uses l-value keep_if internally
226 const auto result_chain = square_is_even_chain(xs); // uses r-value keep_if internally
227 const auto result_fwd_apply = square_is_even_fwd_apply(xs); // uses r-value keep_if internally
228 const auto result_fwd_compose = square_is_even_fwd_compose(xs); // uses r-value keep_if internally
229 }
230