*
* This type is usually used through the 'map' or 'mapped' helper function:
*
- * auto squares = seq(1, 10) | map(square) | asVector;
+ * auto squares = seq(1, 10) | map(square) | as<std::vector>();
*/
template <class Predicate>
class Map : public Operator<Map<Predicate>> {
*
* auto best = from(sortedItems)
* | until([](Item& item) { return item.score > 100; })
- * | asVector;
+ * | as<std::vector>();
*/
template <class Predicate>
class Until : public Operator<Until<Predicate>> {
}
};
+/**
+ * Visit - For calling a function on each item before passing it down the
+ * pipeline.
+ *
+ * This type is usually used through the 'visit' helper function:
+ *
+ * auto printedValues = seq(1) | visit(debugPrint);
+ * // nothing printed yet
+ * auto results = take(10) | as<std::vector>();
+ * // results now populated, 10 values printed
+ */
+template <class Visitor>
+class Visit : public Operator<Visit<Visitor>> {
+ Visitor visitor_;
+
+ public:
+ Visit() = default;
+
+ explicit Visit(Visitor visitor) : visitor_(std::move(visitor)) {}
+
+ template <class Value, class Source>
+ class Generator : public GenImpl<Value, Generator<Value, Source>> {
+ Source source_;
+ Visitor visitor_;
+
+ public:
+ explicit Generator(Source source, const Visitor& visitor)
+ : source_(std::move(source)), visitor_(visitor) {}
+
+ template <class Body>
+ void foreach(Body&& body) const {
+ source_.foreach([&](Value value) {
+ visitor_(value); // not forwarding to avoid accidental moves
+ body(std::forward<Value>(value));
+ });
+ }
+
+ template <class Handler>
+ bool apply(Handler&& handler) const {
+ return source_.apply([&](Value value) {
+ visitor_(value); // not forwarding to avoid accidental moves
+ return handler(std::forward<Value>(value));
+ });
+ }
+
+ static constexpr bool infinite = Source::infinite;
+ };
+
+ template <class Source, class Value, class Gen = Generator<Value, Source>>
+ Gen compose(GenImpl<Value, Source>&& source) const {
+ return Gen(std::move(source.self()), visitor_);
+ }
+
+ template <class Source, class Value, class Gen = Generator<Value, Source>>
+ Gen compose(const GenImpl<Value, Source>& source) const {
+ return Gen(source.self(), visitor_);
+ }
+};
+
/**
* Stride - For producing every Nth value from a source.
*
class Skip;
+template <class Visitor>
+class Visit;
+
template <class Selector, class Comparer = Less>
class Order;
return Filter(std::move(pred));
}
+template <class Visitor = Ignore, class Visit = detail::Visit<Visitor>>
+Visit visit(Visitor visitor = Visitor()) {
+ return Visit(std::move(visitor));
+}
+
template <class Predicate, class Until = detail::Until<Predicate>>
Until until(Predicate pred = Predicate()) {
return Until(std::move(pred));
*
* from(source) | all(pred) == from(source) | filter(negate(pred)) | isEmpty
*/
-
template <
class Predicate = Identity,
class Filter = detail::Filter<Negate<Predicate>>,
UnwrapOr unwrapOr(Fallback&& fallback) {
return UnwrapOr(std::forward<Fallback>(fallback));
}
+
} // gen
} // folly
| as<vector<int>>();
EXPECT_EQ(expected, actual);
}
- */
+ */
+}
+
+TEST(Gen, Visit) {
+ auto increment = [](int& i) { ++i; };
+ auto clone = map([](int i) { return i; });
+ { // apply()
+ auto expected = 10;
+ auto actual = seq(0) | clone | visit(increment) | take(4) | sum;
+ EXPECT_EQ(expected, actual);
+ }
+ { // foreach()
+ auto expected = 10;
+ auto actual = seq(0, 3) | clone | visit(increment) | sum;
+ EXPECT_EQ(expected, actual);
+ }
+ { // tee-like
+ std::vector<int> x2, x4;
+ std::vector<int> expected2{0, 1, 4, 9};
+ std::vector<int> expected4{0, 1, 16, 81};
+
+ auto tee = [](std::vector<int>& container) {
+ return visit([&](int value) { container.push_back(value); });
+ };
+ EXPECT_EQ(
+ 98, seq(0, 3) | map(square) | tee(x2) | map(square) | tee(x4) | sum);
+ EXPECT_EQ(expected2, x2);
+ EXPECT_EQ(expected4, x4);
+ }
}
TEST(Gen, Composed) {
// reference of a std::vector when it is used as the 'other' for an rvalue
// constructor. Use fbvector because we're sure its size will be zero in
// this case.
- fbvector<int> v({1,2,3,4});
+ fbvector<int> v({1, 2, 3, 4});
auto q1 = from(v);
EXPECT_EQ(v.size(), 4); // ensure that the lvalue version was called!
auto expected = 1 * 2 * 3 * 4;
}
{
auto expected = 7;
- auto q = from([] {return vector<int>({3,7,5}); }());
+ auto q = from([] { return vector<int>({3, 7, 5}); }());
EXPECT_EQ(expected, q | max);
}
{
- for (auto size: {5, 1024, 16384, 1<<20}) {
+ for (auto size : {5, 1024, 16384, 1 << 20}) {
auto q1 = from(vector<int>(size, 2));
auto q2 = from(vector<int>(size, 3));
// If the rvalue specialization is broken/gone, then the compiler will