2 * Copyright 2013 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 namespace folly { namespace gen {
20 * IsCompatibleSignature - Trait type for testing whether a given Functor
21 * matches an expected signature.
24 * IsCompatibleSignature<FunctorType, bool(int, float)>::value
26 template<class Candidate, class Expected>
27 class IsCompatibleSignature {
28 static constexpr bool value = false;
31 template<class Candidate,
34 class IsCompatibleSignature<Candidate, ExpectedReturn(ArgTypes...)> {
37 decltype(std::declval<F>()(std::declval<ArgTypes>()...)),
38 bool good = std::is_same<ExpectedReturn, ActualReturn>::value>
39 static constexpr bool testArgs(int* p) {
44 static constexpr bool testArgs(...) {
48 static constexpr bool value = testArgs<Candidate>(nullptr);
52 * ArgumentReference - For determining ideal argument type to receive a value.
55 struct ArgumentReference :
56 public std::conditional<std::is_reference<T>::value,
57 T, // T& -> T&, T&& -> T&&, const T& -> const T&
58 typename std::conditional<
59 std::is_const<T>::value,
60 T&, // const int -> const int&
65 * FBounded - Helper type for the curiously recurring template pattern, used
66 * heavily here to enable inlining and obviate virtual functions
70 const Self& self() const {
71 return *static_cast<const Self*>(this);
75 return *static_cast<Self*>(this);
80 * Operator - Core abstraction of an operation which may be applied to a
81 * generator. All operators implement a method compose(), which takes a
82 * generator and produces an output generator.
85 class Operator : public FBounded<Self> {
88 * compose() - Must be implemented by child class to compose a new Generator
89 * out of a given generator. This function left intentionally unimplemented.
91 template<class Source,
93 class ResultGen = void>
94 ResultGen compose(const GenImpl<Value, Source>& source) const;
98 Operator(const Operator&) = default;
99 Operator(Operator&&) = default;
103 * operator|() - For composing two operators without binding it to a
104 * particular generator.
108 class Composed = detail::Composed<Left, Right>>
109 Composed operator|(const Operator<Left>& left,
110 const Operator<Right>& right) {
111 return Composed(left.self(), right.self());
116 class Composed = detail::Composed<Left, Right>>
117 Composed operator|(const Operator<Left>& left,
118 Operator<Right>&& right) {
119 return Composed(left.self(), std::move(right.self()));
124 class Composed = detail::Composed<Left, Right>>
125 Composed operator|(Operator<Left>&& left,
126 const Operator<Right>& right) {
127 return Composed(std::move(left.self()), right.self());
132 class Composed = detail::Composed<Left, Right>>
133 Composed operator|(Operator<Left>&& left,
134 Operator<Right>&& right) {
135 return Composed(std::move(left.self()), std::move(right.self()));
139 * GenImpl - Core abstraction of a generator, an object which produces values by
140 * passing them to a given handler lambda. All generator implementations must
141 * implement apply(). foreach() may also be implemented to special case the
142 * condition where the entire sequence is consumed.
144 template<class Value,
146 class GenImpl : public FBounded<Self> {
148 // To prevent slicing
150 GenImpl(const GenImpl&) = default;
151 GenImpl(GenImpl&&) = default;
154 typedef Value ValueType;
155 typedef typename std::decay<Value>::type StorageType;
158 * apply() - Send all values produced by this generator to given
159 * handler until it returns false. Returns true if the false iff the handler
162 template<class Handler>
163 bool apply(Handler&& handler) const;
166 * foreach() - Send all values produced by this generator to given lambda.
169 void foreach(Body&& body) const {
170 this->self().apply([&](Value value) -> bool {
171 body(std::forward<Value>(value));
177 template<class LeftValue,
181 class Chain = detail::Chain<LeftValue, Left, Right>>
182 Chain operator+(const GenImpl<LeftValue, Left>& left,
183 const GenImpl<RightValue, Right>& right) {
185 std::is_same<LeftValue, RightValue>::value,
186 "Generators may ony be combined if Values are the exact same type.");
187 return Chain(left.self(), right.self());
190 template<class LeftValue,
194 class Chain = detail::Chain<LeftValue, Left, Right>>
195 Chain operator+(const GenImpl<LeftValue, Left>& left,
196 GenImpl<RightValue, Right>&& right) {
198 std::is_same<LeftValue, RightValue>::value,
199 "Generators may ony be combined if Values are the exact same type.");
200 return Chain(left.self(), std::move(right.self()));
203 template<class LeftValue,
207 class Chain = detail::Chain<LeftValue, Left, Right>>
208 Chain operator+(GenImpl<LeftValue, Left>&& left,
209 const GenImpl<RightValue, Right>& right) {
211 std::is_same<LeftValue, RightValue>::value,
212 "Generators may ony be combined if Values are the exact same type.");
213 return Chain(std::move(left.self()), right.self());
216 template<class LeftValue,
220 class Chain = detail::Chain<LeftValue, Left, Right>>
221 Chain operator+(GenImpl<LeftValue, Left>&& left,
222 GenImpl<RightValue, Right>&& right) {
224 std::is_same<LeftValue, RightValue>::value,
225 "Generators may ony be combined if Values are the exact same type.");
226 return Chain(std::move(left.self()), std::move(right.self()));
230 * operator|() which enables foreach-like usage:
231 * gen | [](Value v) -> void {...};
233 template<class Value,
236 typename std::enable_if<
237 IsCompatibleSignature<Handler, void(Value)>::value>::type
238 operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
239 gen.self().foreach(std::forward<Handler>(handler));
243 * operator|() which enables foreach-like usage with 'break' support:
244 * gen | [](Value v) -> bool { return shouldContinue(); };
246 template<class Value,
249 typename std::enable_if<
250 IsCompatibleSignature<Handler, bool(Value)>::value, bool>::type
251 operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
252 return gen.self().apply(std::forward<Handler>(handler));
256 * operator|() for composing generators with operators, similar to boosts' range
258 * gen | map(square) | sum
260 template<class Value,
263 auto operator|(const GenImpl<Value, Gen>& gen, const Operator<Op>& op) ->
264 decltype(op.self().compose(gen.self())) {
265 return op.self().compose(gen.self());
268 template<class Value,
271 auto operator|(GenImpl<Value, Gen>&& gen, const Operator<Op>& op) ->
272 decltype(op.self().compose(std::move(gen.self()))) {
273 return op.self().compose(std::move(gen.self()));
279 * ReferencedSource - Generate values from an STL-like container using
280 * iterators from .begin() until .end(). Value type defaults to the type of
281 * *container->begin(). For std::vector<int>, this would be int&. Note that the
282 * value here is a reference, so the values in the vector will be passed by
283 * reference to downstream operators.
285 * This type is primarily used through the 'from' helper method, like:
287 * string& longestName = from(names)
288 * | maxBy([](string& s) { return s.size() });
290 template<class Container,
292 class ReferencedSource :
293 public GenImpl<Value, ReferencedSource<Container, Value>> {
294 Container* container_;
296 explicit ReferencedSource(Container* container)
297 : container_(container) {}
300 void foreach(Body&& body) const {
301 for (auto& value : *container_) {
302 body(std::forward<Value>(value));
306 template<class Handler>
307 bool apply(Handler&& handler) const {
308 for (auto& value : *container_) {
309 if (!handler(std::forward<Value>(value))) {
318 * CopiedSource - For producing values from eagerly from a sequence of values
319 * whose storage is owned by this class. Useful for preparing a generator for
320 * use after a source collection will no longer be available, or for when the
321 * values are specified literally with an initializer list.
323 * This type is primarily used through the 'fromCopy' function, like:
325 * auto sourceCopy = fromCopy(makeAVector());
326 * auto sum = sourceCopy | sum;
327 * auto max = sourceCopy | max;
329 * Though it is also used for the initializer_list specialization of from().
331 template<class StorageType,
334 public GenImpl<const StorageType&,
335 CopiedSource<StorageType, Container>> {
337 !std::is_reference<StorageType>::value, "StorageType must be decayed");
339 // Generator objects are often copied during normal construction as they are
340 // encapsulated by downstream generators. It would be bad if this caused
341 // a copy of the entire container each time, and since we're only exposing a
342 // const reference to the value, it's safe to share it between multiple
345 !std::is_reference<Container>::value,
346 "Can't copy into a reference");
347 std::shared_ptr<const Container> copy_;
349 typedef Container ContainerType;
351 template<class SourceContainer>
352 explicit CopiedSource(const SourceContainer& container)
353 : copy_(new Container(begin(container), end(container))) {}
355 explicit CopiedSource(Container&& container) :
356 copy_(new Container(std::move(container))) {}
358 // To enable re-use of cached results.
359 CopiedSource(const CopiedSource<StorageType, Container>& source)
360 : copy_(source.copy_) {}
363 void foreach(Body&& body) const {
364 for (const auto& value : *copy_) {
369 template<class Handler>
370 bool apply(Handler&& handler) const {
371 // The collection may be reused by others, we can't allow it to be changed.
372 for (const auto& value : *copy_) {
373 if (!handler(value)) {
382 * Sequence - For generating values from beginning value, incremented along the
383 * way with the ++ and += operators. Iteration may continue indefinitely by
384 * setting the 'endless' template parameter to true. If set to false, iteration
385 * will stop when value reaches 'end', either inclusively or exclusively,
386 * depending on the template parameter 'endInclusive'. Value type specified
389 * This type is primarily used through the 'seq' and 'range' function, like:
391 * int total = seq(1, 10) | sum;
392 * auto indexes = range(0, 10);
394 template<class Value,
397 class Sequence : public GenImpl<const Value&,
398 Sequence<Value, endless, endInclusive>> {
399 static_assert(!std::is_reference<Value>::value &&
400 !std::is_const<Value>::value, "Value mustn't be const or ref.");
401 Value bounds_[endless ? 1 : 2];
403 explicit Sequence(Value begin)
404 : bounds_{std::move(begin)} {
405 static_assert(endless, "Must supply 'end'");
408 Sequence(Value begin,
410 : bounds_{std::move(begin), std::move(end)} {}
412 template<class Handler>
413 bool apply(Handler&& handler) const {
414 Value value = bounds_[0];
415 for (;endless || value < bounds_[1]; ++value) {
416 const Value& arg = value;
421 if (endInclusive && value == bounds_[1]) {
422 const Value& arg = value;
431 void foreach(Body&& body) const {
432 Value value = bounds_[0];
433 for (;endless || value < bounds_[1]; ++value) {
434 const Value& arg = value;
437 if (endInclusive && value == bounds_[1]) {
438 const Value& arg = value;
445 * Chain - For concatenating the values produced by two Generators.
447 * This type is primarily used through using '+' to combine generators, like:
449 * auto nums = seq(1, 10) + seq(20, 30);
450 * int total = nums | sum;
452 template<class Value, class First, class Second>
453 class Chain : public GenImpl<Value,
454 Chain<Value, First, Second>> {
458 explicit Chain(First first, Second second)
459 : first_(std::move(first))
460 , second_(std::move(second)) {}
462 template<class Handler>
463 bool apply(Handler&& handler) const {
464 return first_.apply(std::forward<Handler>(handler))
465 && second_.apply(std::forward<Handler>(handler));
469 void foreach(Body&& body) const {
470 first_.foreach(std::forward<Body>(body));
471 second_.foreach(std::forward<Body>(body));
476 * GenratorBuilder - Helper for GENERTATOR macro.
478 template<class Value>
479 struct GeneratorBuilder {
480 template<class Source,
481 class Yield = detail::Yield<Value, Source>>
482 Yield operator+(Source&& source) {
483 return Yield(std::forward<Source>(source));
488 * Yield - For producing values from a user-defined generator by way of a
491 template<class Value, class Source>
492 class Yield : public GenImpl<Value, Yield<Value, Source>> {
495 explicit Yield(Source source)
496 : source_(std::move(source)) {
499 template<class Handler>
500 bool apply(Handler&& handler) const {
502 auto body = [&](Value value) {
503 if (!handler(std::forward<Value>(value))) {
516 void foreach(Body&& body) const {
517 source_(std::forward<Body>(body));
527 * Map - For producing a sequence of values by passing each value from a source
528 * collection through a predicate.
530 * This type is usually used through the 'map' or 'mapped' helper function:
532 * auto squares = seq(1, 10) | map(square) | asVector;
534 template<class Predicate>
535 class Map : public Operator<Map<Predicate>> {
540 explicit Map(Predicate pred)
541 : pred_(std::move(pred))
544 template<class Value,
546 class Result = typename ArgumentReference<
547 typename std::result_of<Predicate(Value)>::type
550 public GenImpl<Result, Generator<Value, Source, Result>> {
554 explicit Generator(Source source, const Predicate& pred)
555 : source_(std::move(source)), pred_(pred) {}
558 void foreach(Body&& body) const {
559 source_.foreach([&](Value value) {
560 body(pred_(std::forward<Value>(value)));
564 template<class Handler>
565 bool apply(Handler&& handler) const {
566 return source_.apply([&](Value value) {
567 return handler(pred_(std::forward<Value>(value)));
572 template<class Source,
574 class Gen = Generator<Value, Source>>
575 Gen compose(GenImpl<Value, Source>&& source) const {
576 return Gen(std::move(source.self()), pred_);
579 template<class Source,
581 class Gen = Generator<Value, Source>>
582 Gen compose(const GenImpl<Value, Source>& source) const {
583 return Gen(source.self(), pred_);
589 * Filter - For filtering values from a source sequence by a predicate.
591 * This type is usually used through the 'filter' helper function, like:
593 * auto nonEmpty = from(strings)
594 * | filter([](const string& str) -> bool {
595 * return !str.empty();
598 template<class Predicate>
599 class Filter : public Operator<Filter<Predicate>> {
603 explicit Filter(Predicate pred)
604 : pred_(std::move(pred))
607 template<class Value,
609 class Generator : public GenImpl<Value, Generator<Value, Source>> {
613 explicit Generator(Source source, const Predicate& pred)
614 : source_(std::move(source)), pred_(pred) {}
617 void foreach(Body&& body) const {
618 source_.foreach([&](Value value) {
619 if (pred_(std::forward<Value>(value))) {
620 body(std::forward<Value>(value));
625 template<class Handler>
626 bool apply(Handler&& handler) const {
627 return source_.apply([&](Value value) -> bool {
628 if (pred_(std::forward<Value>(value))) {
629 return handler(std::forward<Value>(value));
636 template<class Source,
638 class Gen = Generator<Value, Source>>
639 Gen compose(GenImpl<Value, Source>&& source) const {
640 return Gen(std::move(source.self()), pred_);
643 template<class Source,
645 class Gen = Generator<Value, Source>>
646 Gen compose(const GenImpl<Value, Source>& source) const {
647 return Gen(source.self(), pred_);
652 * Until - For producing values from a source until a predicate is satisfied.
654 * This type is usually used through the 'until' helper function, like:
656 * auto best = from(sortedItems)
657 * | until([](Item& item) { return item.score > 100; })
660 template<class Predicate>
661 class Until : public Operator<Until<Predicate>> {
665 explicit Until(Predicate pred)
666 : pred_(std::move(pred))
669 template<class Value,
671 class Result = typename std::result_of<Predicate(Value)>::type>
673 public GenImpl<Result, Generator<Value, Source, Result>> {
677 explicit Generator(Source source, const Predicate& pred)
678 : source_(std::move(source)), pred_(pred) {}
680 template<class Handler>
681 bool apply(Handler&& handler) const {
682 return source_.apply([&](Value value) -> bool {
683 return !pred_(std::forward<Value>(value))
684 && handler(std::forward<Value>(value));
689 template<class Source,
691 class Gen = Generator<Value, Source>>
692 Gen compose(GenImpl<Value, Source>&& source) const {
693 return Gen(std::move(source.self()), pred_);
696 template<class Source,
698 class Gen = Generator<Value, Source>>
699 Gen compose(const GenImpl<Value, Source>& source) const {
700 return Gen(source.self(), pred_);
705 * Take - For producing up to N values from a source.
707 * This type is usually used through the 'take' helper function, like:
709 * auto best = from(docs)
710 * | orderByDescending(scoreDoc)
713 class Take : public Operator<Take> {
716 explicit Take(size_t count)
719 template<class Value,
722 public GenImpl<Value, Generator<Value, Source>> {
726 explicit Generator(Source source, size_t count)
727 : source_(std::move(source)) , count_(count) {}
729 template<class Handler>
730 bool apply(Handler&& handler) const {
731 if (count_ == 0) { return false; }
733 return source_.apply([&](Value value) -> bool {
734 if (!handler(std::forward<Value>(value))) {
742 template<class Source,
744 class Gen = Generator<Value, Source>>
745 Gen compose(GenImpl<Value, Source>&& source) const {
746 return Gen(std::move(source.self()), count_);
749 template<class Source,
751 class Gen = Generator<Value, Source>>
752 Gen compose(const GenImpl<Value, Source>& source) const {
753 return Gen(source.self(), count_);
758 * Skip - For skipping N items from the beginning of a source generator.
760 * This type is usually used through the 'skip' helper function, like:
762 * auto page = from(results)
763 * | skip(pageSize * startPage)
766 class Skip : public Operator<Skip> {
769 explicit Skip(size_t count)
772 template<class Value,
775 public GenImpl<Value, Generator<Value, Source>> {
779 explicit Generator(Source source, size_t count)
780 : source_(std::move(source)) , count_(count) {}
783 void foreach(Body&& body) const {
785 source_.foreach(body);
789 source_.foreach([&](Value value) {
793 body(std::forward<Value>(value));
798 template<class Handler>
799 bool apply(Handler&& handler) const {
801 return source_.apply(handler);
804 return source_.apply([&](Value value) -> bool {
809 return handler(std::forward<Value>(value));
814 template<class Source,
816 class Gen = Generator<Value, Source>>
817 Gen compose(GenImpl<Value, Source>&& source) const {
818 return Gen(std::move(source.self()), count_);
821 template<class Source,
823 class Gen = Generator<Value, Source>>
824 Gen compose(const GenImpl<Value, Source>& source) const {
825 return Gen(source.self(), count_);
830 * Order - For ordering a sequence of values from a source by key.
831 * The key is extracted by the given selector functor, and this key is then
832 * compared using the specified comparator.
834 * This type is usually used through the 'order' helper function, like:
836 * auto closest = from(places)
837 * | orderBy([](Place& p) {
838 * return -distance(p.location, here);
842 template<class Selector, class Comparer>
843 class Order : public Operator<Order<Selector, Comparer>> {
849 explicit Order(Selector selector)
850 : selector_(std::move(selector))
853 Order(Selector selector,
855 : selector_(std::move(selector))
856 , comparer_(std::move(comparer))
859 template<class Value,
861 class StorageType = typename std::decay<Value>::type,
862 class Result = typename std::result_of<Selector(Value)>::type>
864 public GenImpl<StorageType&&,
865 Generator<Value, Source, StorageType, Result>> {
870 typedef std::vector<StorageType> VectorType;
872 VectorType asVector() const {
873 auto comparer = [&](const StorageType& a, const StorageType& b) {
874 return comparer_(selector_(a), selector_(b));
876 auto vals = source_ | as<VectorType>();
877 std::sort(vals.begin(), vals.end(), comparer);
878 return std::move(vals);
881 Generator(Source source,
882 const Selector& selector,
883 const Comparer& comparer)
884 : source_(std::move(source)),
886 comparer_(comparer) {}
888 VectorType operator|(const Collect<VectorType>&) const {
892 VectorType operator|(const CollectTemplate<std::vector>&) const {
897 void foreach(Body&& body) const {
898 for (auto& value : asVector()) {
899 body(std::move(value));
903 template<class Handler>
904 bool apply(Handler&& handler) const {
905 auto comparer = [&](const StorageType& a, const StorageType& b) {
906 // swapped for minHeap
907 return comparer_(selector_(b), selector_(a));
909 auto heap = source_ | as<VectorType>();
910 std::make_heap(heap.begin(), heap.end(), comparer);
911 while (!heap.empty()) {
912 std::pop_heap(heap.begin(), heap.end(), comparer);
913 if (!handler(std::move(heap.back()))) {
922 template<class Source,
924 class Gen = Generator<Value, Source>>
925 Gen compose(GenImpl<Value, Source>&& source) const {
926 return Gen(std::move(source.self()), selector_, comparer_);
929 template<class Source,
931 class Gen = Generator<Value, Source>>
932 Gen compose(const GenImpl<Value, Source>& source) const {
933 return Gen(source.self(), selector_, comparer_);
938 * Composed - For building up a pipeline of operations to perform, absent any
939 * particular source generator. Useful for building up custom pipelines.
941 * This type is usually used by just piping two operators together:
943 * auto valuesOf = filter([](Optional<int>& o) { return o.hasValue(); })
944 * | map([](Optional<int>& o) -> int& { return o.value(); });
946 * auto valuesIncluded = from(optionals) | valuesOf | as<vector>();
948 template<class First,
950 class Composed : public Operator<Composed<First, Second>> {
956 Composed(First first, Second second)
957 : first_(std::move(first))
958 , second_(std::move(second)) {}
960 template<class Source,
962 class FirstRet = decltype(std::declval<First>()
963 .compose(std::declval<Source>())),
964 class SecondRet = decltype(std::declval<Second>()
965 .compose(std::declval<FirstRet>()))>
966 SecondRet compose(const GenImpl<Value, Source>& source) const {
967 return second_.compose(first_.compose(source.self()));
970 template<class Source,
972 class FirstRet = decltype(std::declval<First>()
973 .compose(std::declval<Source>())),
974 class SecondRet = decltype(std::declval<Second>()
975 .compose(std::declval<FirstRet>()))>
976 SecondRet compose(GenImpl<Value, Source>&& source) const {
977 return second_.compose(first_.compose(std::move(source.self())));
986 * FoldLeft - Left-associative functional fold. For producing an aggregate value
987 * from a seed and a folder function. Useful for custom aggregators on a
990 * This type is primarily used through the 'foldl' helper method, like:
992 * double movingAverage = from(values)
993 * | foldl(0.0, [](double avg, double sample) {
994 * return sample * 0.1 + avg * 0.9;
999 class FoldLeft : public Operator<FoldLeft<Seed, Fold>> {
1006 : seed_(std::move(seed))
1007 , fold_(std::move(fold))
1010 template<class Source,
1012 Seed compose(const GenImpl<Value, Source>& source) const {
1014 source | [&](Value v) {
1015 accum = fold_(std::move(accum), std::forward<Value>(v));
1022 * First - For finding the first value in a sequence.
1024 * This type is primarily used through the 'first' static value, like:
1026 * int firstThreeDigitPrime = seq(100) | filter(isPrime) | first;
1028 class First : public Operator<First> {
1032 template<class Source,
1034 class StorageType = typename std::decay<Value>::type>
1035 StorageType compose(const GenImpl<Value, Source>& source) const {
1036 Optional<StorageType> accum;
1037 source | [&](Value v) -> bool {
1038 accum = std::forward<Value>(v);
1041 if (!accum.hasValue()) {
1042 throw EmptySequence();
1044 return std::move(accum.value());
1050 * Any - For determining whether any values in a sequence satisfy a predicate.
1052 * This type is primarily used through the 'any' static value, like:
1054 * bool any20xPrimes = seq(200, 210) | filter(isPrime) | any;
1056 * Note that it may also be used like so:
1058 * bool any20xPrimes = seq(200, 210) | any(isPrime);
1061 class Any : public Operator<Any> {
1065 template<class Source,
1067 bool compose(const GenImpl<Value, Source>& source) const {
1069 source | [&](Value v) -> bool {
1077 * Convenience function for use like:
1079 * bool found = gen | any([](int i) { return i * i > 100; });
1081 template<class Predicate,
1082 class Filter = Filter<Predicate>,
1083 class Composed = Composed<Filter, Any>>
1084 Composed operator()(Predicate pred) const {
1085 return Composed(Filter(std::move(pred)), Any());
1090 * All - For determining whether all values in a sequence satisfy a predicate.
1092 * This type is primarily used through the 'any' static value, like:
1094 * bool valid = from(input) | all(validate);
1096 * Note: Passing an empty sequence through 'all()' will always return true.
1098 template<class Predicate>
1099 class All : public Operator<All<Predicate>> {
1103 explicit All(Predicate pred)
1104 : pred_(std::move(pred))
1107 template<class Source,
1109 bool compose(const GenImpl<Value, Source>& source) const {
1111 source | [&](Value v) -> bool {
1112 if (!pred_(std::forward<Value>(v))) {
1123 * Reduce - Functional reduce, for recursively combining values from a source
1124 * using a reducer function until there is only one item left. Useful for
1125 * combining values when an empty sequence doesn't make sense.
1127 * This type is primarily used through the 'reduce' helper method, like:
1129 * sring longest = from(names)
1130 * | reduce([](string&& best, string& current) {
1131 * return best.size() >= current.size() ? best : current;
1134 template<class Reducer>
1135 class Reduce : public Operator<Reduce<Reducer>> {
1139 explicit Reduce(Reducer reducer)
1140 : reducer_(std::move(reducer))
1143 template<class Source,
1145 class StorageType = typename std::decay<Value>::type>
1146 StorageType compose(const GenImpl<Value, Source>& source) const {
1147 Optional<StorageType> accum;
1148 source | [&](Value v) {
1149 if (accum.hasValue()) {
1150 accum = reducer_(std::move(accum.value()), std::forward<Value>(v));
1152 accum = std::forward<Value>(v);
1155 if (!accum.hasValue()) {
1156 throw EmptySequence();
1158 return accum.value();
1163 * Count - for simply counting the items in a collection.
1165 * This type is usually used through its singleton, 'count':
1167 * auto shortPrimes = seq(1, 100) | filter(isPrime) | count;
1169 class Count : public Operator<Count> {
1173 template<class Source,
1175 size_t compose(const GenImpl<Value, Source>& source) const {
1176 return foldl(size_t(0),
1177 [](size_t accum, Value v) {
1184 * Sum - For simply summing up all the values from a source.
1186 * This type is usually used through its singleton, 'sum':
1188 * auto gaussSum = seq(1, 100) | sum;
1190 class Sum : public Operator<Sum> {
1194 template<class Source,
1196 class StorageType = typename std::decay<Value>::type>
1197 StorageType compose(const GenImpl<Value, Source>& source) const {
1198 return foldl(StorageType(0),
1199 [](StorageType&& accum, Value v) {
1200 return std::move(accum) + std::forward<Value>(v);
1206 * Contains - For testing whether a value matching the given value is contained
1209 * This type should be used through the 'contains' helper method, like:
1211 * bool contained = seq(1, 10) | map(square) | contains(49);
1213 template<class Needle>
1214 class Contains : public Operator<Contains<Needle>> {
1217 explicit Contains(Needle needle)
1218 : needle_(std::move(needle))
1221 template<class Source,
1223 class StorageType = typename std::decay<Value>::type>
1224 bool compose(const GenImpl<Value, Source>& source) const {
1225 return !(source | [this](Value value) {
1226 return !(needle_ == std::forward<Value>(value));
1232 * Min - For a value which minimizes a key, where the key is determined by a
1233 * given selector, and compared by given comparer.
1235 * This type is usually used through the singletone 'min' or through the helper
1236 * functions 'minBy' and 'maxBy'.
1238 * auto oldest = from(people)
1239 * | minBy([](Person& p) {
1240 * return p.dateOfBirth;
1243 template<class Selector,
1245 class Min : public Operator<Min<Selector, Comparer>> {
1251 explicit Min(Selector selector)
1252 : selector_(std::move(selector))
1255 Min(Selector selector,
1257 : selector_(std::move(selector))
1258 , comparer_(std::move(comparer))
1261 template<class Value,
1263 class StorageType = typename std::decay<Value>::type,
1264 class Key = typename std::decay<
1265 typename std::result_of<Selector(Value)>::type
1267 StorageType compose(const GenImpl<Value, Source>& source) const {
1268 Optional<StorageType> min;
1269 Optional<Key> minKey;
1270 source | [&](Value v) {
1271 Key key = selector_(std::forward<Value>(v));
1272 if (!minKey.hasValue() || comparer_(key, minKey.value())) {
1274 min = std::forward<Value>(v);
1277 if (!min.hasValue()) {
1278 throw EmptySequence();
1285 * Append - For collecting values from a source into a given output container
1288 * This type is usually used through the helper function 'appendTo', like:
1290 * vector<int64_t> ids;
1291 * from(results) | map([](Person& p) { return p.id })
1294 template<class Collection>
1295 class Append : public Operator<Append<Collection>> {
1296 Collection* collection_;
1298 explicit Append(Collection* collection)
1299 : collection_(collection)
1302 template<class Value,
1304 Collection& compose(const GenImpl<Value, Source>& source) const {
1305 source | [&](Value v) {
1306 collection_->insert(collection_->end(), std::forward<Value>(v));
1308 return *collection_;
1313 * Collect - For collecting values from a source in a collection of the desired
1316 * This type is usually used through the helper function 'as', like:
1318 * std::string upper = from(stringPiece)
1320 * | as<std::string>();
1322 template<class Collection>
1323 class Collect : public Operator<Collect<Collection>> {
1327 template<class Value,
1329 class StorageType = typename std::decay<Value>::type>
1330 Collection compose(const GenImpl<Value, Source>& source) const {
1331 Collection collection;
1332 source | [&](Value v) {
1333 collection.insert(collection.end(), std::forward<Value>(v));
1341 * CollectTemplate - For collecting values from a source in a collection
1342 * constructed using the specified template type. Given the type of values
1343 * produced by the given generator, the collection type will be:
1344 * Container<Value, Allocator<Value>>
1346 * The allocator defaults to std::allocator, so this may be used for the STL
1347 * containers by simply using operators like 'as<set>', 'as<deque>',
1348 * 'as<vector>'. 'as', here is the helper method which is the usual means of
1349 * consturcting this operator.
1353 * set<string> uniqueNames = from(names) | as<set>();
1355 template<template<class, class> class Container,
1356 template<class> class Allocator>
1357 class CollectTemplate : public Operator<CollectTemplate<Container, Allocator>> {
1359 CollectTemplate() { }
1361 template<class Value,
1363 class StorageType = typename std::decay<Value>::type,
1364 class Collection = Container<StorageType, Allocator<StorageType>>>
1365 Collection compose(const GenImpl<Value, Source>& source) const {
1366 Collection collection;
1367 source | [&](Value v) {
1368 collection.insert(collection.end(), std::forward<Value>(v));
1375 * Concat - For flattening generators of generators.
1377 * This type is usually used through the 'concat' static value, like:
1381 * | map([](Node& x) {
1382 * return from(x.neighbors)
1383 * | map([&](Node& y) {
1384 * return Edge(x, y);
1390 class Concat : public Operator<Concat> {
1394 template<class Inner,
1396 class InnerValue = typename std::decay<Inner>::type::ValueType>
1398 public GenImpl<InnerValue, Generator<Inner, Source, InnerValue>> {
1401 explicit Generator(Source source)
1402 : source_(std::move(source)) {}
1404 template<class Handler>
1405 bool apply(Handler&& handler) const {
1406 return source_.apply([&](Inner inner) -> bool {
1407 return inner.apply(std::forward<Handler>(handler));
1411 template<class Body>
1412 void foreach(Body&& body) const {
1413 source_.foreach([&](Inner inner) {
1414 inner.foreach(std::forward<Body>(body));
1419 template<class Value,
1421 class Gen = Generator<Value, Source>>
1422 Gen compose(GenImpl<Value, Source>&& source) const {
1423 return Gen(std::move(source.self()));
1426 template<class Value,
1428 class Gen = Generator<Value, Source>>
1429 Gen compose(const GenImpl<Value, Source>& source) const {
1430 return Gen(source.self());
1435 * RangeConcat - For flattening generators of iterables.
1437 * This type is usually used through the 'rconcat' static value, like:
1439 * map<int, vector<int>> adjacency;
1446 class RangeConcat : public Operator<RangeConcat> {
1450 template<class Source,
1452 class InnerValue = typename ValueTypeOfRange<Range>::RefType>
1454 : public GenImpl<InnerValue, Generator<Source, Range, InnerValue>> {
1457 explicit Generator(Source source)
1458 : source_(std::move(source)) {}
1460 template<class Body>
1461 void foreach(Body&& body) const {
1462 source_.foreach([&](Range range) {
1463 for (auto& value : range) {
1469 template<class Handler>
1470 bool apply(Handler&& handler) const {
1471 return source_.apply([&](Range range) -> bool {
1472 for (auto& value : range) {
1473 if (!handler(value)) {
1482 template<class Value,
1484 class Gen = Generator<Source, Value>>
1485 Gen compose(GenImpl<Value, Source>&& source) const {
1486 return Gen(std::move(source.self()));
1489 template<class Value,
1491 class Gen = Generator<Source, Value>>
1492 Gen compose(const GenImpl<Value, Source>& source) const {
1493 return Gen(source.self());
1500 * VirtualGen<T> - For wrapping template types in simple polymorphic wrapper.
1502 template<class Value>
1503 class VirtualGen : public GenImpl<Value, VirtualGen<Value>> {
1506 virtual ~WrapperBase() {}
1507 virtual bool apply(const std::function<bool(Value)>& handler) const = 0;
1508 virtual void foreach(const std::function<void(Value)>& body) const = 0;
1509 virtual std::unique_ptr<const WrapperBase> clone() const = 0;
1512 template<class Wrapped>
1513 class WrapperImpl : public WrapperBase {
1516 explicit WrapperImpl(Wrapped wrapped)
1517 : wrapped_(std::move(wrapped)) {
1520 virtual bool apply(const std::function<bool(Value)>& handler) const {
1521 return wrapped_.apply(handler);
1524 virtual void foreach(const std::function<void(Value)>& body) const {
1525 wrapped_.foreach(body);
1528 virtual std::unique_ptr<const WrapperBase> clone() const {
1529 return std::unique_ptr<const WrapperBase>(new WrapperImpl(wrapped_));
1533 std::unique_ptr<const WrapperBase> wrapper_;
1536 template<class Self>
1537 /* implicit */ VirtualGen(Self source)
1538 : wrapper_(new WrapperImpl<Self>(std::move(source)))
1541 VirtualGen(VirtualGen&& source)
1542 : wrapper_(std::move(source.wrapper_))
1545 VirtualGen(const VirtualGen& source)
1546 : wrapper_(source.wrapper_->clone())
1549 VirtualGen& operator=(const VirtualGen& source) {
1550 wrapper_.reset(source.wrapper_->clone());
1554 VirtualGen& operator=(VirtualGen&& source) {
1555 wrapper_= std::move(source.wrapper_);
1559 bool apply(const std::function<bool(Value)>& handler) const {
1560 return wrapper_->apply(handler);
1563 void foreach(const std::function<void(Value)>& body) const {
1564 wrapper_->foreach(body);
1569 * non-template operators, statically defined to avoid the need for anything but
1572 static const detail::Sum sum;
1574 static const detail::Count count;
1576 static const detail::First first;
1578 static const detail::Any any;
1580 static const detail::Min<Identity, Less> min;
1582 static const detail::Min<Identity, Greater> max;
1584 static const detail::Order<Identity> order;
1586 static const detail::Map<Move> move;
1588 static const detail::Concat concat;
1590 static const detail::RangeConcat rconcat;
1592 inline detail::Take take(size_t count) {
1593 return detail::Take(count);
1596 inline detail::Skip skip(size_t count) {
1597 return detail::Skip(count);
1600 }} //folly::gen::detail