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 static_assert(!infinite, "Cannot call foreach on infinite GenImpl");
172 body(std::forward<Value>(value));
177 // Child classes should override if the sequence generated is *definitely*
178 // infinite. 'infinite' may be false_type for some infinite sequences
179 // (due the the Halting Problem).
180 static constexpr bool infinite = false;
183 template<class LeftValue,
187 class Chain = detail::Chain<LeftValue, Left, Right>>
188 Chain operator+(const GenImpl<LeftValue, Left>& left,
189 const GenImpl<RightValue, Right>& right) {
191 std::is_same<LeftValue, RightValue>::value,
192 "Generators may ony be combined if Values are the exact same type.");
193 return Chain(left.self(), right.self());
196 template<class LeftValue,
200 class Chain = detail::Chain<LeftValue, Left, Right>>
201 Chain operator+(const GenImpl<LeftValue, Left>& left,
202 GenImpl<RightValue, Right>&& right) {
204 std::is_same<LeftValue, RightValue>::value,
205 "Generators may ony be combined if Values are the exact same type.");
206 return Chain(left.self(), std::move(right.self()));
209 template<class LeftValue,
213 class Chain = detail::Chain<LeftValue, Left, Right>>
214 Chain operator+(GenImpl<LeftValue, Left>&& left,
215 const GenImpl<RightValue, Right>& right) {
217 std::is_same<LeftValue, RightValue>::value,
218 "Generators may ony be combined if Values are the exact same type.");
219 return Chain(std::move(left.self()), right.self());
222 template<class LeftValue,
226 class Chain = detail::Chain<LeftValue, Left, Right>>
227 Chain operator+(GenImpl<LeftValue, Left>&& left,
228 GenImpl<RightValue, Right>&& right) {
230 std::is_same<LeftValue, RightValue>::value,
231 "Generators may ony be combined if Values are the exact same type.");
232 return Chain(std::move(left.self()), std::move(right.self()));
236 * operator|() which enables foreach-like usage:
237 * gen | [](Value v) -> void {...};
239 template<class Value,
242 typename std::enable_if<
243 IsCompatibleSignature<Handler, void(Value)>::value>::type
244 operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
245 static_assert(!Gen::infinite,
246 "Cannot pull all values from an infinite sequence.");
247 gen.self().foreach(std::forward<Handler>(handler));
251 * operator|() which enables foreach-like usage with 'break' support:
252 * gen | [](Value v) -> bool { return shouldContinue(); };
254 template<class Value,
257 typename std::enable_if<
258 IsCompatibleSignature<Handler, bool(Value)>::value, bool>::type
259 operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
260 return gen.self().apply(std::forward<Handler>(handler));
264 * operator|() for composing generators with operators, similar to boosts' range
266 * gen | map(square) | sum
268 template<class Value,
271 auto operator|(const GenImpl<Value, Gen>& gen, const Operator<Op>& op) ->
272 decltype(op.self().compose(gen.self())) {
273 return op.self().compose(gen.self());
276 template<class Value,
279 auto operator|(GenImpl<Value, Gen>&& gen, const Operator<Op>& op) ->
280 decltype(op.self().compose(std::move(gen.self()))) {
281 return op.self().compose(std::move(gen.self()));
287 * ReferencedSource - Generate values from an STL-like container using
288 * iterators from .begin() until .end(). Value type defaults to the type of
289 * *container->begin(). For std::vector<int>, this would be int&. Note that the
290 * value here is a reference, so the values in the vector will be passed by
291 * reference to downstream operators.
293 * This type is primarily used through the 'from' helper method, like:
295 * string& longestName = from(names)
296 * | maxBy([](string& s) { return s.size() });
298 template<class Container,
300 class ReferencedSource :
301 public GenImpl<Value, ReferencedSource<Container, Value>> {
302 Container* container_;
304 explicit ReferencedSource(Container* container)
305 : container_(container) {}
308 void foreach(Body&& body) const {
309 for (auto& value : *container_) {
310 body(std::forward<Value>(value));
314 template<class Handler>
315 bool apply(Handler&& handler) const {
316 for (auto& value : *container_) {
317 if (!handler(std::forward<Value>(value))) {
326 * CopiedSource - For producing values from eagerly from a sequence of values
327 * whose storage is owned by this class. Useful for preparing a generator for
328 * use after a source collection will no longer be available, or for when the
329 * values are specified literally with an initializer list.
331 * This type is primarily used through the 'fromCopy' function, like:
333 * auto sourceCopy = fromCopy(makeAVector());
334 * auto sum = sourceCopy | sum;
335 * auto max = sourceCopy | max;
337 * Though it is also used for the initializer_list specialization of from().
339 template<class StorageType,
342 public GenImpl<const StorageType&,
343 CopiedSource<StorageType, Container>> {
345 !std::is_reference<StorageType>::value, "StorageType must be decayed");
347 // Generator objects are often copied during normal construction as they are
348 // encapsulated by downstream generators. It would be bad if this caused
349 // a copy of the entire container each time, and since we're only exposing a
350 // const reference to the value, it's safe to share it between multiple
353 !std::is_reference<Container>::value,
354 "Can't copy into a reference");
355 std::shared_ptr<const Container> copy_;
357 typedef Container ContainerType;
359 template<class SourceContainer>
360 explicit CopiedSource(const SourceContainer& container)
361 : copy_(new Container(begin(container), end(container))) {}
363 explicit CopiedSource(Container&& container) :
364 copy_(new Container(std::move(container))) {}
366 // To enable re-use of cached results.
367 CopiedSource(const CopiedSource<StorageType, Container>& source)
368 : copy_(source.copy_) {}
371 void foreach(Body&& body) const {
372 for (const auto& value : *copy_) {
377 template<class Handler>
378 bool apply(Handler&& handler) const {
379 // The collection may be reused by others, we can't allow it to be changed.
380 for (const auto& value : *copy_) {
381 if (!handler(value)) {
390 * Sequence - For generating values from beginning value, incremented along the
391 * way with the ++ and += operators. Iteration may continue indefinitely by
392 * setting the 'endless' template parameter to true. If set to false, iteration
393 * will stop when value reaches 'end', either inclusively or exclusively,
394 * depending on the template parameter 'endInclusive'. Value type specified
397 * This type is primarily used through the 'seq' and 'range' function, like:
399 * int total = seq(1, 10) | sum;
400 * auto indexes = range(0, 10);
402 template<class Value,
405 class Sequence : public GenImpl<const Value&,
406 Sequence<Value, endless, endInclusive>> {
407 static_assert(!std::is_reference<Value>::value &&
408 !std::is_const<Value>::value, "Value mustn't be const or ref.");
409 Value bounds_[endless ? 1 : 2];
411 explicit Sequence(Value begin)
412 : bounds_{std::move(begin)} {
413 static_assert(endless, "Must supply 'end'");
416 Sequence(Value begin,
418 : bounds_{std::move(begin), std::move(end)} {}
420 template<class Handler>
421 bool apply(Handler&& handler) const {
422 Value value = bounds_[0];
423 for (;endless || value < bounds_[1]; ++value) {
424 const Value& arg = value;
429 if (endInclusive && value == bounds_[1]) {
430 const Value& arg = value;
439 void foreach(Body&& body) const {
440 Value value = bounds_[0];
441 for (;endless || value < bounds_[1]; ++value) {
442 const Value& arg = value;
445 if (endInclusive && value == bounds_[1]) {
446 const Value& arg = value;
451 static constexpr bool infinite = endless;
455 * Chain - For concatenating the values produced by two Generators.
457 * This type is primarily used through using '+' to combine generators, like:
459 * auto nums = seq(1, 10) + seq(20, 30);
460 * int total = nums | sum;
462 template<class Value, class First, class Second>
463 class Chain : public GenImpl<Value,
464 Chain<Value, First, Second>> {
468 explicit Chain(First first, Second second)
469 : first_(std::move(first))
470 , second_(std::move(second)) {}
472 template<class Handler>
473 bool apply(Handler&& handler) const {
474 return first_.apply(std::forward<Handler>(handler))
475 && second_.apply(std::forward<Handler>(handler));
479 void foreach(Body&& body) const {
480 first_.foreach(std::forward<Body>(body));
481 second_.foreach(std::forward<Body>(body));
484 static constexpr bool infinite = First::infinite || Second::infinite;
488 * GenratorBuilder - Helper for GENERTATOR macro.
490 template<class Value>
491 struct GeneratorBuilder {
492 template<class Source,
493 class Yield = detail::Yield<Value, Source>>
494 Yield operator+(Source&& source) {
495 return Yield(std::forward<Source>(source));
500 * Yield - For producing values from a user-defined generator by way of a
503 template<class Value, class Source>
504 class Yield : public GenImpl<Value, Yield<Value, Source>> {
507 explicit Yield(Source source)
508 : source_(std::move(source)) {
511 template<class Handler>
512 bool apply(Handler&& handler) const {
514 auto body = [&](Value value) {
515 if (!handler(std::forward<Value>(value))) {
528 void foreach(Body&& body) const {
529 source_(std::forward<Body>(body));
539 * Map - For producing a sequence of values by passing each value from a source
540 * collection through a predicate.
542 * This type is usually used through the 'map' or 'mapped' helper function:
544 * auto squares = seq(1, 10) | map(square) | asVector;
546 template<class Predicate>
547 class Map : public Operator<Map<Predicate>> {
552 explicit Map(Predicate pred)
553 : pred_(std::move(pred))
556 template<class Value,
558 class Result = typename ArgumentReference<
559 typename std::result_of<Predicate(Value)>::type
562 public GenImpl<Result, Generator<Value, Source, Result>> {
566 explicit Generator(Source source, const Predicate& pred)
567 : source_(std::move(source)), pred_(pred) {}
570 void foreach(Body&& body) const {
571 source_.foreach([&](Value value) {
572 body(pred_(std::forward<Value>(value)));
576 template<class Handler>
577 bool apply(Handler&& handler) const {
578 return source_.apply([&](Value value) {
579 return handler(pred_(std::forward<Value>(value)));
583 static constexpr bool infinite = Source::infinite;
586 template<class Source,
588 class Gen = Generator<Value, Source>>
589 Gen compose(GenImpl<Value, Source>&& source) const {
590 return Gen(std::move(source.self()), pred_);
593 template<class Source,
595 class Gen = Generator<Value, Source>>
596 Gen compose(const GenImpl<Value, Source>& source) const {
597 return Gen(source.self(), pred_);
603 * Filter - For filtering values from a source sequence by a predicate.
605 * This type is usually used through the 'filter' helper function, like:
607 * auto nonEmpty = from(strings)
608 * | filter([](const string& str) -> bool {
609 * return !str.empty();
612 template<class Predicate>
613 class Filter : public Operator<Filter<Predicate>> {
617 explicit Filter(Predicate pred)
618 : pred_(std::move(pred))
621 template<class Value,
623 class Generator : public GenImpl<Value, Generator<Value, Source>> {
627 explicit Generator(Source source, const Predicate& pred)
628 : source_(std::move(source)), pred_(pred) {}
631 void foreach(Body&& body) const {
632 source_.foreach([&](Value value) {
633 if (pred_(std::forward<Value>(value))) {
634 body(std::forward<Value>(value));
639 template<class Handler>
640 bool apply(Handler&& handler) const {
641 return source_.apply([&](Value value) -> bool {
642 if (pred_(std::forward<Value>(value))) {
643 return handler(std::forward<Value>(value));
649 static constexpr bool infinite = Source::infinite;
652 template<class Source,
654 class Gen = Generator<Value, Source>>
655 Gen compose(GenImpl<Value, Source>&& source) const {
656 return Gen(std::move(source.self()), pred_);
659 template<class Source,
661 class Gen = Generator<Value, Source>>
662 Gen compose(const GenImpl<Value, Source>& source) const {
663 return Gen(source.self(), pred_);
668 * Until - For producing values from a source until a predicate is satisfied.
670 * This type is usually used through the 'until' helper function, like:
672 * auto best = from(sortedItems)
673 * | until([](Item& item) { return item.score > 100; })
676 template<class Predicate>
677 class Until : public Operator<Until<Predicate>> {
681 explicit Until(Predicate pred)
682 : pred_(std::move(pred))
685 template<class Value,
687 class Result = typename std::result_of<Predicate(Value)>::type>
689 public GenImpl<Result, Generator<Value, Source, Result>> {
693 explicit Generator(Source source, const Predicate& pred)
694 : source_(std::move(source)), pred_(pred) {}
696 template<class Handler>
697 bool apply(Handler&& handler) const {
698 return source_.apply([&](Value value) -> bool {
699 return !pred_(std::forward<Value>(value))
700 && handler(std::forward<Value>(value));
705 template<class Source,
707 class Gen = Generator<Value, Source>>
708 Gen compose(GenImpl<Value, Source>&& source) const {
709 return Gen(std::move(source.self()), pred_);
712 template<class Source,
714 class Gen = Generator<Value, Source>>
715 Gen compose(const GenImpl<Value, Source>& source) const {
716 return Gen(source.self(), pred_);
719 // Theoretically an 'until' might stop an infinite
720 static constexpr bool infinite = false;
724 * Take - For producing up to N values from a source.
726 * This type is usually used through the 'take' helper function, like:
728 * auto best = from(docs)
729 * | orderByDescending(scoreDoc)
732 class Take : public Operator<Take> {
735 explicit Take(size_t count)
738 template<class Value,
741 public GenImpl<Value, Generator<Value, Source>> {
745 explicit Generator(Source source, size_t count)
746 : source_(std::move(source)) , count_(count) {}
748 template<class Handler>
749 bool apply(Handler&& handler) const {
750 if (count_ == 0) { return false; }
752 return source_.apply([&](Value value) -> bool {
753 if (!handler(std::forward<Value>(value))) {
761 template<class Source,
763 class Gen = Generator<Value, Source>>
764 Gen compose(GenImpl<Value, Source>&& source) const {
765 return Gen(std::move(source.self()), count_);
768 template<class Source,
770 class Gen = Generator<Value, Source>>
771 Gen compose(const GenImpl<Value, Source>& source) const {
772 return Gen(source.self(), count_);
777 * Skip - For skipping N items from the beginning of a source generator.
779 * This type is usually used through the 'skip' helper function, like:
781 * auto page = from(results)
782 * | skip(pageSize * startPage)
785 class Skip : public Operator<Skip> {
788 explicit Skip(size_t count)
791 template<class Value,
794 public GenImpl<Value, Generator<Value, Source>> {
798 explicit Generator(Source source, size_t count)
799 : source_(std::move(source)) , count_(count) {}
802 void foreach(Body&& body) const {
804 source_.foreach(body);
808 source_.foreach([&](Value value) {
812 body(std::forward<Value>(value));
817 template<class Handler>
818 bool apply(Handler&& handler) const {
820 return source_.apply(handler);
823 return source_.apply([&](Value value) -> bool {
828 return handler(std::forward<Value>(value));
832 static constexpr bool infinite = Source::infinite;
835 template<class Source,
837 class Gen = Generator<Value, Source>>
838 Gen compose(GenImpl<Value, Source>&& source) const {
839 return Gen(std::move(source.self()), count_);
842 template<class Source,
844 class Gen = Generator<Value, Source>>
845 Gen compose(const GenImpl<Value, Source>& source) const {
846 return Gen(source.self(), count_);
851 * Order - For ordering a sequence of values from a source by key.
852 * The key is extracted by the given selector functor, and this key is then
853 * compared using the specified comparator.
855 * This type is usually used through the 'order' helper function, like:
857 * auto closest = from(places)
858 * | orderBy([](Place& p) {
859 * return -distance(p.location, here);
863 template<class Selector, class Comparer>
864 class Order : public Operator<Order<Selector, Comparer>> {
870 explicit Order(Selector selector)
871 : selector_(std::move(selector))
874 Order(Selector selector,
876 : selector_(std::move(selector))
877 , comparer_(std::move(comparer))
880 template<class Value,
882 class StorageType = typename std::decay<Value>::type,
883 class Result = typename std::result_of<Selector(Value)>::type>
885 public GenImpl<StorageType&&,
886 Generator<Value, Source, StorageType, Result>> {
887 static_assert(!Source::infinite, "Cannot sort infinite source!");
892 typedef std::vector<StorageType> VectorType;
894 VectorType asVector() const {
895 auto comparer = [&](const StorageType& a, const StorageType& b) {
896 return comparer_(selector_(a), selector_(b));
898 auto vals = source_ | as<VectorType>();
899 std::sort(vals.begin(), vals.end(), comparer);
900 return std::move(vals);
903 Generator(Source source,
904 const Selector& selector,
905 const Comparer& comparer)
906 : source_(std::move(source)),
908 comparer_(comparer) {}
910 VectorType operator|(const Collect<VectorType>&) const {
914 VectorType operator|(const CollectTemplate<std::vector>&) const {
919 void foreach(Body&& body) const {
920 for (auto& value : asVector()) {
921 body(std::move(value));
925 template<class Handler>
926 bool apply(Handler&& handler) const {
927 auto comparer = [&](const StorageType& a, const StorageType& b) {
928 // swapped for minHeap
929 return comparer_(selector_(b), selector_(a));
931 auto heap = source_ | as<VectorType>();
932 std::make_heap(heap.begin(), heap.end(), comparer);
933 while (!heap.empty()) {
934 std::pop_heap(heap.begin(), heap.end(), comparer);
935 if (!handler(std::move(heap.back()))) {
944 template<class Source,
946 class Gen = Generator<Value, Source>>
947 Gen compose(GenImpl<Value, Source>&& source) const {
948 return Gen(std::move(source.self()), selector_, comparer_);
951 template<class Source,
953 class Gen = Generator<Value, Source>>
954 Gen compose(const GenImpl<Value, Source>& source) const {
955 return Gen(source.self(), selector_, comparer_);
960 * Composed - For building up a pipeline of operations to perform, absent any
961 * particular source generator. Useful for building up custom pipelines.
963 * This type is usually used by just piping two operators together:
965 * auto valuesOf = filter([](Optional<int>& o) { return o.hasValue(); })
966 * | map([](Optional<int>& o) -> int& { return o.value(); });
968 * auto valuesIncluded = from(optionals) | valuesOf | as<vector>();
970 template<class First,
972 class Composed : public Operator<Composed<First, Second>> {
978 Composed(First first, Second second)
979 : first_(std::move(first))
980 , second_(std::move(second)) {}
982 template<class Source,
984 class FirstRet = decltype(std::declval<First>()
985 .compose(std::declval<Source>())),
986 class SecondRet = decltype(std::declval<Second>()
987 .compose(std::declval<FirstRet>()))>
988 SecondRet compose(const GenImpl<Value, Source>& source) const {
989 return second_.compose(first_.compose(source.self()));
992 template<class Source,
994 class FirstRet = decltype(std::declval<First>()
995 .compose(std::declval<Source>())),
996 class SecondRet = decltype(std::declval<Second>()
997 .compose(std::declval<FirstRet>()))>
998 SecondRet compose(GenImpl<Value, Source>&& source) const {
999 return second_.compose(first_.compose(std::move(source.self())));
1008 * FoldLeft - Left-associative functional fold. For producing an aggregate value
1009 * from a seed and a folder function. Useful for custom aggregators on a
1012 * This type is primarily used through the 'foldl' helper method, like:
1014 * double movingAverage = from(values)
1015 * | foldl(0.0, [](double avg, double sample) {
1016 * return sample * 0.1 + avg * 0.9;
1019 template<class Seed,
1021 class FoldLeft : public Operator<FoldLeft<Seed, Fold>> {
1028 : seed_(std::move(seed))
1029 , fold_(std::move(fold))
1032 template<class Source,
1034 Seed compose(const GenImpl<Value, Source>& source) const {
1035 static_assert(!Source::infinite, "Cannot foldl infinite source");
1037 source | [&](Value v) {
1038 accum = fold_(std::move(accum), std::forward<Value>(v));
1045 * First - For finding the first value in a sequence.
1047 * This type is primarily used through the 'first' static value, like:
1049 * int firstThreeDigitPrime = seq(100) | filter(isPrime) | first;
1051 class First : public Operator<First> {
1055 template<class Source,
1057 class StorageType = typename std::decay<Value>::type>
1058 StorageType compose(const GenImpl<Value, Source>& source) const {
1059 Optional<StorageType> accum;
1060 source | [&](Value v) -> bool {
1061 accum = std::forward<Value>(v);
1064 if (!accum.hasValue()) {
1065 throw EmptySequence();
1067 return std::move(accum.value());
1073 * Any - For determining whether any values in a sequence satisfy a predicate.
1075 * This type is primarily used through the 'any' static value, like:
1077 * bool any20xPrimes = seq(200, 210) | filter(isPrime) | any;
1079 * Note that it may also be used like so:
1081 * bool any20xPrimes = seq(200, 210) | any(isPrime);
1084 class Any : public Operator<Any> {
1088 template<class Source,
1090 bool compose(const GenImpl<Value, Source>& source) const {
1092 source | [&](Value v) -> bool {
1100 * Convenience function for use like:
1102 * bool found = gen | any([](int i) { return i * i > 100; });
1104 template<class Predicate,
1105 class Filter = Filter<Predicate>,
1106 class Composed = Composed<Filter, Any>>
1107 Composed operator()(Predicate pred) const {
1108 return Composed(Filter(std::move(pred)), Any());
1113 * All - For determining whether all values in a sequence satisfy a predicate.
1115 * This type is primarily used through the 'any' static value, like:
1117 * bool valid = from(input) | all(validate);
1119 * Note: Passing an empty sequence through 'all()' will always return true.
1121 template<class Predicate>
1122 class All : public Operator<All<Predicate>> {
1126 explicit All(Predicate pred)
1127 : pred_(std::move(pred))
1130 template<class Source,
1132 bool compose(const GenImpl<Value, Source>& source) const {
1133 static_assert(!Source::infinite, "Cannot call 'all' on infinite source");
1135 source | [&](Value v) -> bool {
1136 if (!pred_(std::forward<Value>(v))) {
1147 * Reduce - Functional reduce, for recursively combining values from a source
1148 * using a reducer function until there is only one item left. Useful for
1149 * combining values when an empty sequence doesn't make sense.
1151 * This type is primarily used through the 'reduce' helper method, like:
1153 * sring longest = from(names)
1154 * | reduce([](string&& best, string& current) {
1155 * return best.size() >= current.size() ? best : current;
1158 template<class Reducer>
1159 class Reduce : public Operator<Reduce<Reducer>> {
1163 explicit Reduce(Reducer reducer)
1164 : reducer_(std::move(reducer))
1167 template<class Source,
1169 class StorageType = typename std::decay<Value>::type>
1170 StorageType compose(const GenImpl<Value, Source>& source) const {
1171 Optional<StorageType> accum;
1172 source | [&](Value v) {
1173 if (accum.hasValue()) {
1174 accum = reducer_(std::move(accum.value()), std::forward<Value>(v));
1176 accum = std::forward<Value>(v);
1179 if (!accum.hasValue()) {
1180 throw EmptySequence();
1182 return accum.value();
1187 * Count - for simply counting the items in a collection.
1189 * This type is usually used through its singleton, 'count':
1191 * auto shortPrimes = seq(1, 100) | filter(isPrime) | count;
1193 class Count : public Operator<Count> {
1197 template<class Source,
1199 size_t compose(const GenImpl<Value, Source>& source) const {
1200 static_assert(!Source::infinite, "Cannot count infinite source");
1201 return foldl(size_t(0),
1202 [](size_t accum, Value v) {
1209 * Sum - For simply summing up all the values from a source.
1211 * This type is usually used through its singleton, 'sum':
1213 * auto gaussSum = seq(1, 100) | sum;
1215 class Sum : public Operator<Sum> {
1217 template<class Source,
1219 class StorageType = typename std::decay<Value>::type>
1220 StorageType compose(const GenImpl<Value, Source>& source) const {
1221 static_assert(!Source::infinite, "Cannot sum infinite source");
1222 return foldl(StorageType(0),
1223 [](StorageType&& accum, Value v) {
1224 return std::move(accum) + std::forward<Value>(v);
1230 * Contains - For testing whether a value matching the given value is contained
1233 * This type should be used through the 'contains' helper method, like:
1235 * bool contained = seq(1, 10) | map(square) | contains(49);
1237 template<class Needle>
1238 class Contains : public Operator<Contains<Needle>> {
1241 explicit Contains(Needle needle)
1242 : needle_(std::move(needle))
1245 template<class Source,
1247 class StorageType = typename std::decay<Value>::type>
1248 bool compose(const GenImpl<Value, Source>& source) const {
1249 static_assert(!Source::infinite,
1250 "Calling contains on an infinite source might cause "
1251 "an infinite loop.");
1252 return !(source | [this](Value value) {
1253 return !(needle_ == std::forward<Value>(value));
1259 * Min - For a value which minimizes a key, where the key is determined by a
1260 * given selector, and compared by given comparer.
1262 * This type is usually used through the singletone 'min' or through the helper
1263 * functions 'minBy' and 'maxBy'.
1265 * auto oldest = from(people)
1266 * | minBy([](Person& p) {
1267 * return p.dateOfBirth;
1270 template<class Selector,
1272 class Min : public Operator<Min<Selector, Comparer>> {
1278 explicit Min(Selector selector)
1279 : selector_(std::move(selector))
1282 Min(Selector selector,
1284 : selector_(std::move(selector))
1285 , comparer_(std::move(comparer))
1288 template<class Value,
1290 class StorageType = typename std::decay<Value>::type,
1291 class Key = typename std::decay<
1292 typename std::result_of<Selector(Value)>::type
1294 StorageType compose(const GenImpl<Value, Source>& source) const {
1295 Optional<StorageType> min;
1296 Optional<Key> minKey;
1297 source | [&](Value v) {
1298 Key key = selector_(std::forward<Value>(v));
1299 if (!minKey.hasValue() || comparer_(key, minKey.value())) {
1301 min = std::forward<Value>(v);
1304 if (!min.hasValue()) {
1305 throw EmptySequence();
1312 * Append - For collecting values from a source into a given output container
1315 * This type is usually used through the helper function 'appendTo', like:
1317 * vector<int64_t> ids;
1318 * from(results) | map([](Person& p) { return p.id })
1321 template<class Collection>
1322 class Append : public Operator<Append<Collection>> {
1323 Collection* collection_;
1325 explicit Append(Collection* collection)
1326 : collection_(collection)
1329 template<class Value,
1331 Collection& compose(const GenImpl<Value, Source>& source) const {
1332 source | [&](Value v) {
1333 collection_->insert(collection_->end(), std::forward<Value>(v));
1335 return *collection_;
1340 * Collect - For collecting values from a source in a collection of the desired
1343 * This type is usually used through the helper function 'as', like:
1345 * std::string upper = from(stringPiece)
1347 * | as<std::string>();
1349 template<class Collection>
1350 class Collect : public Operator<Collect<Collection>> {
1354 template<class Value,
1356 class StorageType = typename std::decay<Value>::type>
1357 Collection compose(const GenImpl<Value, Source>& source) const {
1358 Collection collection;
1359 source | [&](Value v) {
1360 collection.insert(collection.end(), std::forward<Value>(v));
1368 * CollectTemplate - For collecting values from a source in a collection
1369 * constructed using the specified template type. Given the type of values
1370 * produced by the given generator, the collection type will be:
1371 * Container<Value, Allocator<Value>>
1373 * The allocator defaults to std::allocator, so this may be used for the STL
1374 * containers by simply using operators like 'as<set>', 'as<deque>',
1375 * 'as<vector>'. 'as', here is the helper method which is the usual means of
1376 * consturcting this operator.
1380 * set<string> uniqueNames = from(names) | as<set>();
1382 template<template<class, class> class Container,
1383 template<class> class Allocator>
1384 class CollectTemplate : public Operator<CollectTemplate<Container, Allocator>> {
1386 CollectTemplate() { }
1388 template<class Value,
1390 class StorageType = typename std::decay<Value>::type,
1391 class Collection = Container<StorageType, Allocator<StorageType>>>
1392 Collection compose(const GenImpl<Value, Source>& source) const {
1393 Collection collection;
1394 source | [&](Value v) {
1395 collection.insert(collection.end(), std::forward<Value>(v));
1402 * Concat - For flattening generators of generators.
1404 * This type is usually used through the 'concat' static value, like:
1408 * | map([](Node& x) {
1409 * return from(x.neighbors)
1410 * | map([&](Node& y) {
1411 * return Edge(x, y);
1417 class Concat : public Operator<Concat> {
1421 template<class Inner,
1423 class InnerValue = typename std::decay<Inner>::type::ValueType>
1425 public GenImpl<InnerValue, Generator<Inner, Source, InnerValue>> {
1428 explicit Generator(Source source)
1429 : source_(std::move(source)) {}
1431 template<class Handler>
1432 bool apply(Handler&& handler) const {
1433 return source_.apply([&](Inner inner) -> bool {
1434 return inner.apply(std::forward<Handler>(handler));
1438 template<class Body>
1439 void foreach(Body&& body) const {
1440 source_.foreach([&](Inner inner) {
1441 inner.foreach(std::forward<Body>(body));
1445 static constexpr bool infinite = Source::infinite;
1448 template<class Value,
1450 class Gen = Generator<Value, Source>>
1451 Gen compose(GenImpl<Value, Source>&& source) const {
1452 return Gen(std::move(source.self()));
1455 template<class Value,
1457 class Gen = Generator<Value, Source>>
1458 Gen compose(const GenImpl<Value, Source>& source) const {
1459 return Gen(source.self());
1464 * RangeConcat - For flattening generators of iterables.
1466 * This type is usually used through the 'rconcat' static value, like:
1468 * map<int, vector<int>> adjacency;
1475 class RangeConcat : public Operator<RangeConcat> {
1479 template<class Source,
1481 class InnerValue = typename ValueTypeOfRange<Range>::RefType>
1483 : public GenImpl<InnerValue, Generator<Source, Range, InnerValue>> {
1486 explicit Generator(Source source)
1487 : source_(std::move(source)) {}
1489 template<class Body>
1490 void foreach(Body&& body) const {
1491 source_.foreach([&](Range range) {
1492 for (auto& value : range) {
1498 template<class Handler>
1499 bool apply(Handler&& handler) const {
1500 return source_.apply([&](Range range) -> bool {
1501 for (auto& value : range) {
1502 if (!handler(value)) {
1511 template<class Value,
1513 class Gen = Generator<Source, Value>>
1514 Gen compose(GenImpl<Value, Source>&& source) const {
1515 return Gen(std::move(source.self()));
1518 template<class Value,
1520 class Gen = Generator<Source, Value>>
1521 Gen compose(const GenImpl<Value, Source>& source) const {
1522 return Gen(source.self());
1529 * VirtualGen<T> - For wrapping template types in simple polymorphic wrapper.
1531 template<class Value>
1532 class VirtualGen : public GenImpl<Value, VirtualGen<Value>> {
1535 virtual ~WrapperBase() {}
1536 virtual bool apply(const std::function<bool(Value)>& handler) const = 0;
1537 virtual void foreach(const std::function<void(Value)>& body) const = 0;
1538 virtual std::unique_ptr<const WrapperBase> clone() const = 0;
1541 template<class Wrapped>
1542 class WrapperImpl : public WrapperBase {
1545 explicit WrapperImpl(Wrapped wrapped)
1546 : wrapped_(std::move(wrapped)) {
1549 virtual bool apply(const std::function<bool(Value)>& handler) const {
1550 return wrapped_.apply(handler);
1553 virtual void foreach(const std::function<void(Value)>& body) const {
1554 wrapped_.foreach(body);
1557 virtual std::unique_ptr<const WrapperBase> clone() const {
1558 return std::unique_ptr<const WrapperBase>(new WrapperImpl(wrapped_));
1562 std::unique_ptr<const WrapperBase> wrapper_;
1565 template<class Self>
1566 /* implicit */ VirtualGen(Self source)
1567 : wrapper_(new WrapperImpl<Self>(std::move(source)))
1570 VirtualGen(VirtualGen&& source)
1571 : wrapper_(std::move(source.wrapper_))
1574 VirtualGen(const VirtualGen& source)
1575 : wrapper_(source.wrapper_->clone())
1578 VirtualGen& operator=(const VirtualGen& source) {
1579 wrapper_.reset(source.wrapper_->clone());
1583 VirtualGen& operator=(VirtualGen&& source) {
1584 wrapper_= std::move(source.wrapper_);
1588 bool apply(const std::function<bool(Value)>& handler) const {
1589 return wrapper_->apply(handler);
1592 void foreach(const std::function<void(Value)>& body) const {
1593 wrapper_->foreach(body);
1598 * non-template operators, statically defined to avoid the need for anything but
1601 static const detail::Sum sum;
1603 static const detail::Count count;
1605 static const detail::First first;
1607 static const detail::Any any;
1609 static const detail::Min<Identity, Less> min;
1611 static const detail::Min<Identity, Greater> max;
1613 static const detail::Order<Identity> order;
1615 static const detail::Map<Move> move;
1617 static const detail::Concat concat;
1619 static const detail::RangeConcat rconcat;
1621 inline detail::Take take(size_t count) {
1622 return detail::Take(count);
1625 inline detail::Skip skip(size_t count) {
1626 return detail::Skip(count);
1629 }} //folly::gen::detail