2 * Copyright 2014 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 #ifndef FOLLY_GEN_BASE_H
18 #error This file may only be included from folly/gen/Base.h
21 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
22 #pragma GCC diagnostic push
23 #pragma GCC diagnostic ignored "-Wshadow"
25 namespace folly { namespace gen {
28 * ArgumentReference - For determining ideal argument type to receive a value.
31 struct ArgumentReference
32 : public std::conditional<
33 std::is_reference<T>::value,
34 T, // T& -> T&, T&& -> T&&, const T& -> const T&
35 typename std::conditional<std::is_const<T>::value,
36 T&, // const int -> const int&
43 * ReferencedSource - Generate values from an STL-like container using
44 * iterators from .begin() until .end(). Value type defaults to the type of
45 * *container->begin(). For std::vector<int>, this would be int&. Note that the
46 * value here is a reference, so the values in the vector will be passed by
47 * reference to downstream operators.
49 * This type is primarily used through the 'from' helper method, like:
51 * string& longestName = from(names)
52 * | maxBy([](string& s) { return s.size() });
54 template<class Container,
56 class ReferencedSource :
57 public GenImpl<Value, ReferencedSource<Container, Value>> {
58 Container* container_;
60 explicit ReferencedSource(Container* container)
61 : container_(container) {}
64 void foreach(Body&& body) const {
65 for (auto& value : *container_) {
66 body(std::forward<Value>(value));
70 template<class Handler>
71 bool apply(Handler&& handler) const {
72 for (auto& value : *container_) {
73 if (!handler(std::forward<Value>(value))) {
82 * CopiedSource - For producing values from eagerly from a sequence of values
83 * whose storage is owned by this class. Useful for preparing a generator for
84 * use after a source collection will no longer be available, or for when the
85 * values are specified literally with an initializer list.
87 * This type is primarily used through the 'fromCopy' function, like:
89 * auto sourceCopy = fromCopy(makeAVector());
90 * auto sum = sourceCopy | sum;
91 * auto max = sourceCopy | max;
93 * Though it is also used for the initializer_list specialization of from().
95 template<class StorageType,
98 public GenImpl<const StorageType&,
99 CopiedSource<StorageType, Container>> {
101 !std::is_reference<StorageType>::value, "StorageType must be decayed");
103 // Generator objects are often copied during normal construction as they are
104 // encapsulated by downstream generators. It would be bad if this caused
105 // a copy of the entire container each time, and since we're only exposing a
106 // const reference to the value, it's safe to share it between multiple
109 !std::is_reference<Container>::value,
110 "Can't copy into a reference");
111 std::shared_ptr<const Container> copy_;
113 typedef Container ContainerType;
115 template<class SourceContainer>
116 explicit CopiedSource(const SourceContainer& container)
117 : copy_(new Container(begin(container), end(container))) {}
119 explicit CopiedSource(Container&& container) :
120 copy_(new Container(std::move(container))) {}
122 // To enable re-use of cached results.
123 CopiedSource(const CopiedSource<StorageType, Container>& source)
124 : copy_(source.copy_) {}
127 void foreach(Body&& body) const {
128 for (const auto& value : *copy_) {
133 template<class Handler>
134 bool apply(Handler&& handler) const {
135 // The collection may be reused by others, we can't allow it to be changed.
136 for (const auto& value : *copy_) {
137 if (!handler(value)) {
146 * Sequence - For generating values from beginning value, incremented along the
147 * way with the ++ and += operators. Iteration may continue indefinitely by
148 * setting the 'endless' template parameter to true. If set to false, iteration
149 * will stop when value reaches 'end', either inclusively or exclusively,
150 * depending on the template parameter 'endInclusive'. Value type specified
153 * This type is primarily used through the 'seq' and 'range' function, like:
155 * int total = seq(1, 10) | sum;
156 * auto indexes = range(0, 10);
158 template<class Value,
161 class Sequence : public GenImpl<const Value&,
162 Sequence<Value, endless, endInclusive>> {
163 static_assert(!std::is_reference<Value>::value &&
164 !std::is_const<Value>::value, "Value mustn't be const or ref.");
165 Value bounds_[endless ? 1 : 2];
167 explicit Sequence(Value begin)
168 : bounds_{std::move(begin)} {
169 static_assert(endless, "Must supply 'end'");
172 Sequence(Value begin,
174 : bounds_{std::move(begin), std::move(end)} {}
176 template<class Handler>
177 bool apply(Handler&& handler) const {
178 Value value = bounds_[0];
179 for (;endless || value < bounds_[1]; ++value) {
180 const Value& arg = value;
185 if (endInclusive && value == bounds_[1]) {
186 const Value& arg = value;
195 void foreach(Body&& body) const {
196 Value value = bounds_[0];
197 for (;endless || value < bounds_[1]; ++value) {
198 const Value& arg = value;
201 if (endInclusive && value == bounds_[1]) {
202 const Value& arg = value;
207 static constexpr bool infinite = endless;
211 * GenratorBuilder - Helper for GENERTATOR macro.
213 template<class Value>
214 struct GeneratorBuilder {
215 template<class Source,
216 class Yield = detail::Yield<Value, Source>>
217 Yield operator+(Source&& source) {
218 return Yield(std::forward<Source>(source));
223 * Yield - For producing values from a user-defined generator by way of a
226 template<class Value, class Source>
227 class Yield : public GenImpl<Value, Yield<Value, Source>> {
230 explicit Yield(Source source)
231 : source_(std::move(source)) {
234 template<class Handler>
235 bool apply(Handler&& handler) const {
237 auto body = [&](Value value) {
238 if (!handler(std::forward<Value>(value))) {
251 void foreach(Body&& body) const {
252 source_(std::forward<Body>(body));
256 template<class Value>
257 class Empty : public GenImpl<Value, Empty<Value>> {
259 template<class Handler>
260 bool apply(Handler&&) const { return true; }
268 * Map - For producing a sequence of values by passing each value from a source
269 * collection through a predicate.
271 * This type is usually used through the 'map' or 'mapped' helper function:
273 * auto squares = seq(1, 10) | map(square) | asVector;
275 template<class Predicate>
276 class Map : public Operator<Map<Predicate>> {
281 explicit Map(Predicate pred)
282 : pred_(std::move(pred))
285 template<class Value,
287 class Result = typename ArgumentReference<
288 typename std::result_of<Predicate(Value)>::type
291 public GenImpl<Result, Generator<Value, Source, Result>> {
295 explicit Generator(Source source, const Predicate& pred)
296 : source_(std::move(source)), pred_(pred) {}
299 void foreach(Body&& body) const {
300 source_.foreach([&](Value value) {
301 body(pred_(std::forward<Value>(value)));
305 template<class Handler>
306 bool apply(Handler&& handler) const {
307 return source_.apply([&](Value value) {
308 return handler(pred_(std::forward<Value>(value)));
312 static constexpr bool infinite = Source::infinite;
315 template<class Source,
317 class Gen = Generator<Value, Source>>
318 Gen compose(GenImpl<Value, Source>&& source) const {
319 return Gen(std::move(source.self()), pred_);
322 template<class Source,
324 class Gen = Generator<Value, Source>>
325 Gen compose(const GenImpl<Value, Source>& source) const {
326 return Gen(source.self(), pred_);
332 * Filter - For filtering values from a source sequence by a predicate.
334 * This type is usually used through the 'filter' helper function, like:
336 * auto nonEmpty = from(strings)
337 * | filter([](const string& str) -> bool {
338 * return !str.empty();
341 template<class Predicate>
342 class Filter : public Operator<Filter<Predicate>> {
346 explicit Filter(Predicate pred)
347 : pred_(std::move(pred))
350 template<class Value,
352 class Generator : public GenImpl<Value, Generator<Value, Source>> {
356 explicit Generator(Source source, const Predicate& pred)
357 : source_(std::move(source)), pred_(pred) {}
360 void foreach(Body&& body) const {
361 source_.foreach([&](Value value) {
362 if (pred_(std::forward<Value>(value))) {
363 body(std::forward<Value>(value));
368 template<class Handler>
369 bool apply(Handler&& handler) const {
370 return source_.apply([&](Value value) -> bool {
371 if (pred_(std::forward<Value>(value))) {
372 return handler(std::forward<Value>(value));
378 static constexpr bool infinite = Source::infinite;
381 template<class Source,
383 class Gen = Generator<Value, Source>>
384 Gen compose(GenImpl<Value, Source>&& source) const {
385 return Gen(std::move(source.self()), pred_);
388 template<class Source,
390 class Gen = Generator<Value, Source>>
391 Gen compose(const GenImpl<Value, Source>& source) const {
392 return Gen(source.self(), pred_);
397 * Until - For producing values from a source until a predicate is satisfied.
399 * This type is usually used through the 'until' helper function, like:
401 * auto best = from(sortedItems)
402 * | until([](Item& item) { return item.score > 100; })
405 template<class Predicate>
406 class Until : public Operator<Until<Predicate>> {
410 explicit Until(Predicate pred)
411 : pred_(std::move(pred))
414 template<class Value,
416 class Generator : public GenImpl<Value, Generator<Value, Source>> {
420 explicit Generator(Source source, const Predicate& pred)
421 : source_(std::move(source)), pred_(pred) {}
423 template<class Handler>
424 bool apply(Handler&& handler) const {
425 bool cancelled = false;
426 source_.apply([&](Value value) -> bool {
427 if (pred_(value)) { // un-forwarded to disable move
430 if (!handler(std::forward<Value>(value))) {
440 template<class Source,
442 class Gen = Generator<Value, Source>>
443 Gen compose(GenImpl<Value, Source>&& source) const {
444 return Gen(std::move(source.self()), pred_);
447 template<class Source,
449 class Gen = Generator<Value, Source>>
450 Gen compose(const GenImpl<Value, Source>& source) const {
451 return Gen(source.self(), pred_);
454 // Theoretically an 'until' might stop an infinite
455 static constexpr bool infinite = false;
459 * Take - For producing up to N values from a source.
461 * This type is usually used through the 'take' helper function, like:
463 * auto best = from(docs)
464 * | orderByDescending(scoreDoc)
467 class Take : public Operator<Take> {
470 explicit Take(size_t count)
473 template<class Value,
476 public GenImpl<Value, Generator<Value, Source>> {
480 explicit Generator(Source source, size_t count)
481 : source_(std::move(source)) , count_(count) {}
483 template<class Handler>
484 bool apply(Handler&& handler) const {
485 if (count_ == 0) { return false; }
487 bool cancelled = false;
488 source_.apply([&](Value value) -> bool {
489 if (!handler(std::forward<Value>(value))) {
499 template<class Source,
501 class Gen = Generator<Value, Source>>
502 Gen compose(GenImpl<Value, Source>&& source) const {
503 return Gen(std::move(source.self()), count_);
506 template<class Source,
508 class Gen = Generator<Value, Source>>
509 Gen compose(const GenImpl<Value, Source>& source) const {
510 return Gen(source.self(), count_);
515 * Sample - For taking a random sample of N elements from a sequence
516 * (without replacement).
518 template<class Random>
519 class Sample : public Operator<Sample<Random>> {
523 explicit Sample(size_t count, Random rng)
524 : count_(count), rng_(std::move(rng)) {}
526 template<class Value,
529 class StorageType = typename std::decay<Value>::type>
531 public GenImpl<StorageType&&,
532 Generator<Value, Source, Rand, StorageType>> {
533 static_assert(!Source::infinite, "Cannot sample infinite source!");
534 // It's too easy to bite ourselves if random generator is only 16-bit
535 static_assert(Random::max() >= std::numeric_limits<int32_t>::max() - 1,
536 "Random number generator must support big values");
541 explicit Generator(Source source, size_t count, Random rng)
542 : source_(std::move(source)) , count_(count), rng_(std::move(rng)) {}
544 template<class Handler>
545 bool apply(Handler&& handler) const {
546 if (count_ == 0) { return false; }
547 std::vector<StorageType> v;
549 // use reservoir sampling to give each source value an equal chance
550 // of appearing in our output.
552 source_.foreach([&](Value value) -> void {
553 if (v.size() < count_) {
554 v.push_back(std::forward<Value>(value));
556 // alternatively, we could create a std::uniform_int_distribution
557 // instead of using modulus, but benchmarks show this has
558 // substantial overhead.
559 size_t index = rng_() % n;
560 if (index < v.size()) {
561 v[index] = std::forward<Value>(value);
567 // output is unsorted!
569 if (!handler(std::move(val))) {
577 template<class Source,
579 class Gen = Generator<Value, Source, Random>>
580 Gen compose(GenImpl<Value, Source>&& source) const {
581 return Gen(std::move(source.self()), count_, rng_);
584 template<class Source,
586 class Gen = Generator<Value, Source, Random>>
587 Gen compose(const GenImpl<Value, Source>& source) const {
588 return Gen(source.self(), count_, rng_);
593 * Skip - For skipping N items from the beginning of a source generator.
595 * This type is usually used through the 'skip' helper function, like:
597 * auto page = from(results)
598 * | skip(pageSize * startPage)
601 class Skip : public Operator<Skip> {
604 explicit Skip(size_t count)
607 template<class Value,
610 public GenImpl<Value, Generator<Value, Source>> {
614 explicit Generator(Source source, size_t count)
615 : source_(std::move(source)) , count_(count) {}
618 void foreach(Body&& body) const {
620 source_.foreach(body);
624 source_.foreach([&](Value value) {
628 body(std::forward<Value>(value));
633 template<class Handler>
634 bool apply(Handler&& handler) const {
636 return source_.apply(std::forward<Handler>(handler));
639 return source_.apply([&](Value value) -> bool {
644 return handler(std::forward<Value>(value));
648 static constexpr bool infinite = Source::infinite;
651 template<class Source,
653 class Gen = Generator<Value, Source>>
654 Gen compose(GenImpl<Value, Source>&& source) const {
655 return Gen(std::move(source.self()), count_);
658 template<class Source,
660 class Gen = Generator<Value, Source>>
661 Gen compose(const GenImpl<Value, Source>& source) const {
662 return Gen(source.self(), count_);
667 * Order - For ordering a sequence of values from a source by key.
668 * The key is extracted by the given selector functor, and this key is then
669 * compared using the specified comparator.
671 * This type is usually used through the 'order' helper function, like:
673 * auto closest = from(places)
674 * | orderBy([](Place& p) {
675 * return -distance(p.location, here);
679 template<class Selector, class Comparer>
680 class Order : public Operator<Order<Selector, Comparer>> {
686 explicit Order(Selector selector)
687 : selector_(std::move(selector))
690 Order(Selector selector,
692 : selector_(std::move(selector))
693 , comparer_(std::move(comparer))
696 template<class Value,
698 class StorageType = typename std::decay<Value>::type,
699 class Result = typename std::result_of<Selector(Value)>::type>
701 public GenImpl<StorageType&&,
702 Generator<Value, Source, StorageType, Result>> {
703 static_assert(!Source::infinite, "Cannot sort infinite source!");
708 typedef std::vector<StorageType> VectorType;
710 VectorType asVector() const {
711 auto comparer = [&](const StorageType& a, const StorageType& b) {
712 return comparer_(selector_(a), selector_(b));
714 auto vals = source_ | as<VectorType>();
715 std::sort(vals.begin(), vals.end(), comparer);
716 return std::move(vals);
719 Generator(Source source,
722 : source_(std::move(source)),
723 selector_(std::move(selector)),
724 comparer_(std::move(comparer)) {}
726 VectorType operator|(const Collect<VectorType>&) const {
730 VectorType operator|(const CollectTemplate<std::vector>&) const {
735 void foreach(Body&& body) const {
736 for (auto& value : asVector()) {
737 body(std::move(value));
741 template<class Handler>
742 bool apply(Handler&& handler) const {
743 auto comparer = [&](const StorageType& a, const StorageType& b) {
744 // swapped for minHeap
745 return comparer_(selector_(b), selector_(a));
747 auto heap = source_ | as<VectorType>();
748 std::make_heap(heap.begin(), heap.end(), comparer);
749 while (!heap.empty()) {
750 std::pop_heap(heap.begin(), heap.end(), comparer);
751 if (!handler(std::move(heap.back()))) {
760 template<class Source,
762 class Gen = Generator<Value, Source>>
763 Gen compose(GenImpl<Value, Source>&& source) const {
764 return Gen(std::move(source.self()), selector_, comparer_);
767 template<class Source,
769 class Gen = Generator<Value, Source>>
770 Gen compose(const GenImpl<Value, Source>& source) const {
771 return Gen(source.self(), selector_, comparer_);
776 * TypeAssertion - For verifying the exact type of the value produced by a
777 * generator. Useful for testing and debugging, and acts as a no-op at runtime.
778 * Pass-through at runtime. Used through the 'assert_type<>()' factory method
781 * auto c = from(vector) | assert_type<int&>() | sum;
784 template<class Expected>
785 class TypeAssertion : public Operator<TypeAssertion<Expected>> {
787 template<class Source, class Value>
788 const Source& compose(const GenImpl<Value, Source>& source) const {
789 static_assert(std::is_same<Expected, Value>::value,
790 "assert_type() check failed");
791 return source.self();
794 template<class Source, class Value>
795 Source&& compose(GenImpl<Value, Source>&& source) const {
796 static_assert(std::is_same<Expected, Value>::value,
797 "assert_type() check failed");
798 return std::move(source.self());
803 * Distinct - For filtering duplicates out of a sequence. A selector may be
804 * provided to generate a key to uniquify for each value.
806 * This type is usually used through the 'distinct' helper function, like:
808 * auto closest = from(results)
809 * | distinctBy([](Item& i) {
814 template<class Selector>
815 class Distinct : public Operator<Distinct<Selector>> {
820 explicit Distinct(Selector selector)
821 : selector_(std::move(selector))
824 template<class Value,
826 class Generator : public GenImpl<Value, Generator<Value, Source>> {
830 typedef typename std::decay<Value>::type StorageType;
832 // selector_ cannot be passed an rvalue or it would end up passing the husk
833 // of a value to the downstream operators.
834 typedef const StorageType& ParamType;
836 typedef typename std::result_of<Selector(ParamType)>::type KeyType;
837 typedef typename std::decay<KeyType>::type KeyStorageType;
840 Generator(Source source,
842 : source_(std::move(source)),
843 selector_(std::move(selector)) {}
846 void foreach(Body&& body) const {
847 std::unordered_set<KeyStorageType> keysSeen;
848 source_.foreach([&](Value value) {
849 if (keysSeen.insert(selector_(ParamType(value))).second) {
850 body(std::forward<Value>(value));
855 template<class Handler>
856 bool apply(Handler&& handler) const {
857 std::unordered_set<KeyStorageType> keysSeen;
858 return source_.apply([&](Value value) -> bool {
859 if (keysSeen.insert(selector_(ParamType(value))).second) {
860 return handler(std::forward<Value>(value));
867 template<class Source,
869 class Gen = Generator<Value, Source>>
870 Gen compose(GenImpl<Value, Source>&& source) const {
871 return Gen(std::move(source.self()), selector_);
874 template<class Source,
876 class Gen = Generator<Value, Source>>
877 Gen compose(const GenImpl<Value, Source>& source) const {
878 return Gen(source.self(), selector_);
883 * Batch - For producing fixed-size batches of each value from a source.
885 * This type is usually used through the 'batch' helper function:
890 * | map([](const std::vector<int>& batch) {
891 * return from(batch) | sum;
895 class Batch : public Operator<Batch> {
898 explicit Batch(size_t batchSize)
899 : batchSize_(batchSize) {
900 if (batchSize_ == 0) {
901 throw std::invalid_argument("Batch size must be non-zero!");
905 template<class Value,
907 class StorageType = typename std::decay<Value>::type,
908 class VectorType = std::vector<StorageType>>
910 public GenImpl<VectorType&,
911 Generator<Value, Source, StorageType, VectorType>> {
915 explicit Generator(Source source, size_t batchSize)
916 : source_(std::move(source))
917 , batchSize_(batchSize) {}
919 template<class Handler>
920 bool apply(Handler&& handler) const {
922 batch_.reserve(batchSize_);
923 bool shouldContinue = source_.apply([&](Value value) -> bool {
924 batch_.push_back(std::forward<Value>(value));
925 if (batch_.size() == batchSize_) {
926 bool needMore = handler(batch_);
930 // Always need more if the handler is not called.
933 // Flush everything, if and only if `handler` hasn't returned false.
934 if (shouldContinue && !batch_.empty()) {
935 shouldContinue = handler(batch_);
938 return shouldContinue;
941 static constexpr bool infinite = Source::infinite;
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()), batchSize_);
951 template<class Source,
953 class Gen = Generator<Value, Source>>
954 Gen compose(const GenImpl<Value, Source>& source) const {
955 return Gen(source.self(), batchSize_);
963 * FoldLeft - Left-associative functional fold. For producing an aggregate value
964 * from a seed and a folder function. Useful for custom aggregators on a
967 * This type is primarily used through the 'foldl' helper method, like:
969 * double movingAverage = from(values)
970 * | foldl(0.0, [](double avg, double sample) {
971 * return sample * 0.1 + avg * 0.9;
976 class FoldLeft : public Operator<FoldLeft<Seed, Fold>> {
983 : seed_(std::move(seed))
984 , fold_(std::move(fold))
987 template<class Source,
989 Seed compose(const GenImpl<Value, Source>& source) const {
990 static_assert(!Source::infinite, "Cannot foldl infinite source");
992 source | [&](Value v) {
993 accum = fold_(std::move(accum), std::forward<Value>(v));
1000 * First - For finding the first value in a sequence.
1002 * This type is primarily used through the 'first' static value, like:
1004 * int firstThreeDigitPrime = seq(100) | filter(isPrime) | first;
1006 class First : public Operator<First> {
1010 template<class Source,
1012 class StorageType = typename std::decay<Value>::type>
1013 StorageType compose(const GenImpl<Value, Source>& source) const {
1014 Optional<StorageType> accum;
1015 source | [&](Value v) -> bool {
1016 accum = std::forward<Value>(v);
1019 if (!accum.hasValue()) {
1020 throw EmptySequence();
1022 return std::move(accum.value());
1028 * Any - For determining whether any values in a sequence satisfy a predicate.
1030 * This type is primarily used through the 'any' static value, like:
1032 * bool any20xPrimes = seq(200, 210) | filter(isPrime) | any;
1034 * Note that it may also be used like so:
1036 * bool any20xPrimes = seq(200, 210) | any(isPrime);
1039 class Any : public Operator<Any> {
1043 template<class Source,
1045 bool compose(const GenImpl<Value, Source>& source) const {
1047 source | [&](Value v) -> bool {
1055 * Convenience function for use like:
1057 * bool found = gen | any([](int i) { return i * i > 100; });
1059 template<class Predicate,
1060 class Filter = Filter<Predicate>,
1061 class Composed = Composed<Filter, Any>>
1062 Composed operator()(Predicate pred) const {
1063 return Composed(Filter(std::move(pred)), Any());
1068 * All - For determining whether all values in a sequence satisfy a predicate.
1070 * This type is primarily used through the 'any' static value, like:
1072 * bool valid = from(input) | all(validate);
1074 * Note: Passing an empty sequence through 'all()' will always return true.
1076 template<class Predicate>
1077 class All : public Operator<All<Predicate>> {
1081 explicit All(Predicate pred)
1082 : pred_(std::move(pred))
1085 template<class Source,
1087 bool compose(const GenImpl<Value, Source>& source) const {
1088 static_assert(!Source::infinite, "Cannot call 'all' on infinite source");
1090 source | [&](Value v) -> bool {
1091 if (!pred_(std::forward<Value>(v))) {
1102 * Reduce - Functional reduce, for recursively combining values from a source
1103 * using a reducer function until there is only one item left. Useful for
1104 * combining values when an empty sequence doesn't make sense.
1106 * This type is primarily used through the 'reduce' helper method, like:
1108 * sring longest = from(names)
1109 * | reduce([](string&& best, string& current) {
1110 * return best.size() >= current.size() ? best : current;
1113 template<class Reducer>
1114 class Reduce : public Operator<Reduce<Reducer>> {
1118 explicit Reduce(Reducer reducer)
1119 : reducer_(std::move(reducer))
1122 template<class Source,
1124 class StorageType = typename std::decay<Value>::type>
1125 StorageType compose(const GenImpl<Value, Source>& source) const {
1126 Optional<StorageType> accum;
1127 source | [&](Value v) {
1128 if (accum.hasValue()) {
1129 accum = reducer_(std::move(accum.value()), std::forward<Value>(v));
1131 accum = std::forward<Value>(v);
1134 if (!accum.hasValue()) {
1135 throw EmptySequence();
1137 return accum.value();
1142 * Count - for simply counting the items in a collection.
1144 * This type is usually used through its singleton, 'count':
1146 * auto shortPrimes = seq(1, 100) | filter(isPrime) | count;
1148 class Count : public Operator<Count> {
1152 template<class Source,
1154 size_t compose(const GenImpl<Value, Source>& source) const {
1155 static_assert(!Source::infinite, "Cannot count infinite source");
1156 return foldl(size_t(0),
1157 [](size_t accum, Value v) {
1164 * Sum - For simply summing up all the values from a source.
1166 * This type is usually used through its singleton, 'sum':
1168 * auto gaussSum = seq(1, 100) | sum;
1170 class Sum : public Operator<Sum> {
1172 Sum() : Operator<Sum>() {}
1174 template<class Source,
1176 class StorageType = typename std::decay<Value>::type>
1177 StorageType compose(const GenImpl<Value, Source>& source) const {
1178 static_assert(!Source::infinite, "Cannot sum infinite source");
1179 return foldl(StorageType(0),
1180 [](StorageType&& accum, Value v) {
1181 return std::move(accum) + std::forward<Value>(v);
1187 * Contains - For testing whether a value matching the given value is contained
1190 * This type should be used through the 'contains' helper method, like:
1192 * bool contained = seq(1, 10) | map(square) | contains(49);
1194 template<class Needle>
1195 class Contains : public Operator<Contains<Needle>> {
1198 explicit Contains(Needle needle)
1199 : needle_(std::move(needle))
1202 template<class Source,
1204 class StorageType = typename std::decay<Value>::type>
1205 bool compose(const GenImpl<Value, Source>& source) const {
1206 static_assert(!Source::infinite,
1207 "Calling contains on an infinite source might cause "
1208 "an infinite loop.");
1209 return !(source | [this](Value value) {
1210 return !(needle_ == std::forward<Value>(value));
1216 * Min - For a value which minimizes a key, where the key is determined by a
1217 * given selector, and compared by given comparer.
1219 * This type is usually used through the singletone 'min' or through the helper
1220 * functions 'minBy' and 'maxBy'.
1222 * auto oldest = from(people)
1223 * | minBy([](Person& p) {
1224 * return p.dateOfBirth;
1227 template<class Selector,
1229 class Min : public Operator<Min<Selector, Comparer>> {
1235 explicit Min(Selector selector)
1236 : selector_(std::move(selector))
1239 Min(Selector selector,
1241 : selector_(std::move(selector))
1242 , comparer_(std::move(comparer))
1245 template<class Value,
1247 class StorageType = typename std::decay<Value>::type,
1248 class Key = typename std::decay<
1249 typename std::result_of<Selector(Value)>::type
1251 StorageType compose(const GenImpl<Value, Source>& source) const {
1252 Optional<StorageType> min;
1253 Optional<Key> minKey;
1254 source | [&](Value v) {
1255 Key key = selector_(std::forward<Value>(v));
1256 if (!minKey.hasValue() || comparer_(key, minKey.value())) {
1258 min = std::forward<Value>(v);
1261 if (!min.hasValue()) {
1262 throw EmptySequence();
1269 * Append - For collecting values from a source into a given output container
1272 * This type is usually used through the helper function 'appendTo', like:
1274 * vector<int64_t> ids;
1275 * from(results) | map([](Person& p) { return p.id })
1278 template<class Collection>
1279 class Append : public Operator<Append<Collection>> {
1280 Collection* collection_;
1282 explicit Append(Collection* collection)
1283 : collection_(collection)
1286 template<class Value,
1288 Collection& compose(const GenImpl<Value, Source>& source) const {
1289 source | [&](Value v) {
1290 collection_->insert(collection_->end(), std::forward<Value>(v));
1292 return *collection_;
1297 * Collect - For collecting values from a source in a collection of the desired
1300 * This type is usually used through the helper function 'as', like:
1302 * std::string upper = from(stringPiece)
1304 * | as<std::string>();
1306 template<class Collection>
1307 class Collect : public Operator<Collect<Collection>> {
1311 template<class Value,
1313 class StorageType = typename std::decay<Value>::type>
1314 Collection compose(const GenImpl<Value, Source>& source) const {
1315 Collection collection;
1316 source | [&](Value v) {
1317 collection.insert(collection.end(), std::forward<Value>(v));
1325 * CollectTemplate - For collecting values from a source in a collection
1326 * constructed using the specified template type. Given the type of values
1327 * produced by the given generator, the collection type will be:
1328 * Container<Value, Allocator<Value>>
1330 * The allocator defaults to std::allocator, so this may be used for the STL
1331 * containers by simply using operators like 'as<set>', 'as<deque>',
1332 * 'as<vector>'. 'as', here is the helper method which is the usual means of
1333 * consturcting this operator.
1337 * set<string> uniqueNames = from(names) | as<set>();
1339 template<template<class, class> class Container,
1340 template<class> class Allocator>
1341 class CollectTemplate : public Operator<CollectTemplate<Container, Allocator>> {
1343 CollectTemplate() { }
1345 template<class Value,
1347 class StorageType = typename std::decay<Value>::type,
1348 class Collection = Container<StorageType, Allocator<StorageType>>>
1349 Collection compose(const GenImpl<Value, Source>& source) const {
1350 Collection collection;
1351 source | [&](Value v) {
1352 collection.insert(collection.end(), std::forward<Value>(v));
1359 * Concat - For flattening generators of generators.
1361 * This type is usually used through the 'concat' static value, like:
1365 * | map([](Node& x) {
1366 * return from(x.neighbors)
1367 * | map([&](Node& y) {
1368 * return Edge(x, y);
1374 class Concat : public Operator<Concat> {
1378 template<class Inner,
1380 class InnerValue = typename std::decay<Inner>::type::ValueType>
1382 public GenImpl<InnerValue, Generator<Inner, Source, InnerValue>> {
1385 explicit Generator(Source source)
1386 : source_(std::move(source)) {}
1388 template<class Handler>
1389 bool apply(Handler&& handler) const {
1390 return source_.apply([&](Inner inner) -> bool {
1391 return inner.apply(std::forward<Handler>(handler));
1395 template<class Body>
1396 void foreach(Body&& body) const {
1397 source_.foreach([&](Inner inner) {
1398 inner.foreach(std::forward<Body>(body));
1402 static constexpr bool infinite = Source::infinite;
1405 template<class Value,
1407 class Gen = Generator<Value, Source>>
1408 Gen compose(GenImpl<Value, Source>&& source) const {
1409 return Gen(std::move(source.self()));
1412 template<class Value,
1414 class Gen = Generator<Value, Source>>
1415 Gen compose(const GenImpl<Value, Source>& source) const {
1416 return Gen(source.self());
1421 * RangeConcat - For flattening generators of iterables.
1423 * This type is usually used through the 'rconcat' static value, like:
1425 * map<int, vector<int>> adjacency;
1432 class RangeConcat : public Operator<RangeConcat> {
1436 template<class Range,
1438 class InnerValue = typename ValueTypeOfRange<Range>::RefType>
1440 : public GenImpl<InnerValue, Generator<Range, Source, InnerValue>> {
1443 explicit Generator(Source source)
1444 : source_(std::move(source)) {}
1446 template<class Body>
1447 void foreach(Body&& body) const {
1448 source_.foreach([&](Range range) {
1449 for (auto& value : range) {
1455 template<class Handler>
1456 bool apply(Handler&& handler) const {
1457 return source_.apply([&](Range range) -> bool {
1458 for (auto& value : range) {
1459 if (!handler(value)) {
1468 template<class Value,
1470 class Gen = Generator<Value, Source>>
1471 Gen compose(GenImpl<Value, Source>&& source) const {
1472 return Gen(std::move(source.self()));
1475 template<class Value,
1477 class Gen = Generator<Value, Source>>
1478 Gen compose(const GenImpl<Value, Source>& source) const {
1479 return Gen(source.self());
1485 * GuardImpl - For handling exceptions from downstream computation. Requires the
1486 * type of exception to catch, and handler function to invoke in the event of
1487 * the exception. Note that the handler may:
1488 * 1) return true to continue processing the sequence
1489 * 2) return false to end the sequence immediately
1490 * 3) throw, to pass the exception to the next catch
1491 * The handler must match the signature 'bool(Exception&, Value)'.
1493 * This type is used through the `guard` helper, like so:
1496 * = byLine(STDIN_FILENO)
1497 * | guard<std::runtime_error>([](std::runtime_error& e,
1499 * LOG(ERROR) << sp << ": " << e.str();
1500 * return true; // continue processing subsequent lines
1505 * TODO(tjackson): Rename this back to Guard.
1507 template<class Exception,
1509 class GuardImpl : public Operator<GuardImpl<Exception, ErrorHandler>> {
1510 ErrorHandler handler_;
1512 GuardImpl(ErrorHandler handler)
1513 : handler_(std::move(handler)) {}
1515 template<class Value,
1517 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1519 ErrorHandler handler_;
1521 explicit Generator(Source source,
1522 ErrorHandler handler)
1523 : source_(std::move(source)),
1524 handler_(std::move(handler)) {}
1526 template<class Handler>
1527 bool apply(Handler&& handler) const {
1528 return source_.apply([&](Value value) -> bool {
1530 handler(std::forward<Value>(value));
1532 } catch (Exception& e) {
1533 return handler_(e, std::forward<Value>(value));
1538 static constexpr bool infinite = Source::infinite;
1541 template<class Value,
1543 class Gen = Generator<Value, Source>>
1544 Gen compose(GenImpl<Value, Source>&& source) const {
1545 return Gen(std::move(source.self()), handler_);
1548 template<class Value,
1550 class Gen = Generator<Value, Source>>
1551 Gen compose(const GenImpl<Value, Source>& source) const {
1552 return Gen(source.self(), handler_);
1557 * Cycle - For repeating a sequence forever.
1559 * This type is usually used through the 'cycle' static value, like:
1566 class Cycle : public Operator<Cycle> {
1567 off_t limit_; // -1 for infinite
1572 explicit Cycle(off_t limit)
1575 template<class Value,
1577 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1579 off_t limit_; // -1 for infinite
1581 explicit Generator(Source source, off_t limit)
1582 : source_(std::move(source))
1585 template<class Handler>
1586 bool apply(Handler&& handler) const {
1588 auto handler2 = [&](Value value) {
1589 cont = handler(std::forward<Value>(value));
1592 for (off_t count = 0; count != limit_; ++count) {
1594 source_.apply(handler2);
1602 // not actually infinite, since an empty generator will end the cycles.
1603 static constexpr bool infinite = Source::infinite;
1606 template<class Source,
1608 class Gen = Generator<Value, Source>>
1609 Gen compose(GenImpl<Value, Source>&& source) const {
1610 return Gen(std::move(source.self()), limit_);
1613 template<class Source,
1615 class Gen = Generator<Value, Source>>
1616 Gen compose(const GenImpl<Value, Source>& source) const {
1617 return Gen(source.self(), limit_);
1621 * Convenience function for use like:
1623 * auto tripled = gen | cycle(3);
1625 Cycle operator()(off_t limit) const {
1626 return Cycle(limit);
1631 * Dereference - For dereferencing a sequence of pointers while filtering out
1634 * This type is usually used through the 'dereference' static value, like:
1636 * auto refs = from(ptrs) | dereference;
1638 class Dereference : public Operator<Dereference> {
1642 template<class Value,
1644 class Result = decltype(*std::declval<Value>())>
1645 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
1648 explicit Generator(Source source)
1649 : source_(std::move(source)) {}
1651 template<class Body>
1652 void foreach(Body&& body) const {
1653 source_.foreach([&](Value value) {
1655 return body(*value);
1660 template<class Handler>
1661 bool apply(Handler&& handler) const {
1662 return source_.apply([&](Value value) -> bool {
1664 return handler(*value);
1670 // not actually infinite, since an empty generator will end the cycles.
1671 static constexpr bool infinite = Source::infinite;
1674 template<class Source,
1676 class Gen = Generator<Value, Source>>
1677 Gen compose(GenImpl<Value, Source>&& source) const {
1678 return Gen(std::move(source.self()));
1681 template<class Source,
1683 class Gen = Generator<Value, Source>>
1684 Gen compose(const GenImpl<Value, Source>& source) const {
1685 return Gen(source.self());
1692 * VirtualGen<T> - For wrapping template types in simple polymorphic wrapper.
1694 template<class Value>
1695 class VirtualGen : public GenImpl<Value, VirtualGen<Value>> {
1698 virtual ~WrapperBase() {}
1699 virtual bool apply(const std::function<bool(Value)>& handler) const = 0;
1700 virtual void foreach(const std::function<void(Value)>& body) const = 0;
1701 virtual std::unique_ptr<const WrapperBase> clone() const = 0;
1704 template<class Wrapped>
1705 class WrapperImpl : public WrapperBase {
1708 explicit WrapperImpl(Wrapped wrapped)
1709 : wrapped_(std::move(wrapped)) {
1712 virtual bool apply(const std::function<bool(Value)>& handler) const {
1713 return wrapped_.apply(handler);
1716 virtual void foreach(const std::function<void(Value)>& body) const {
1717 wrapped_.foreach(body);
1720 virtual std::unique_ptr<const WrapperBase> clone() const {
1721 return std::unique_ptr<const WrapperBase>(new WrapperImpl(wrapped_));
1725 std::unique_ptr<const WrapperBase> wrapper_;
1728 template<class Self>
1729 /* implicit */ VirtualGen(Self source)
1730 : wrapper_(new WrapperImpl<Self>(std::move(source)))
1733 VirtualGen(VirtualGen&& source)
1734 : wrapper_(std::move(source.wrapper_))
1737 VirtualGen(const VirtualGen& source)
1738 : wrapper_(source.wrapper_->clone())
1741 VirtualGen& operator=(const VirtualGen& source) {
1742 wrapper_.reset(source.wrapper_->clone());
1746 VirtualGen& operator=(VirtualGen&& source) {
1747 wrapper_= std::move(source.wrapper_);
1751 bool apply(const std::function<bool(Value)>& handler) const {
1752 return wrapper_->apply(handler);
1755 void foreach(const std::function<void(Value)>& body) const {
1756 wrapper_->foreach(body);
1761 * non-template operators, statically defined to avoid the need for anything but
1764 static const detail::Sum sum;
1766 static const detail::Count count;
1768 static const detail::First first;
1771 * Use directly for detecting any values, or as a function to detect values
1772 * which pass a predicate:
1774 * auto nonempty = g | any;
1775 * auto evens = g | any(even);
1777 static const detail::Any any;
1779 static const detail::Min<Identity, Less> min;
1781 static const detail::Min<Identity, Greater> max;
1783 static const detail::Order<Identity> order;
1785 static const detail::Distinct<Identity> distinct;
1787 static const detail::Map<Move> move;
1789 static const detail::Concat concat;
1791 static const detail::RangeConcat rconcat;
1794 * Use directly for infinite sequences, or as a function to limit cycle count.
1796 * auto forever = g | cycle;
1797 * auto thrice = g | cycle(3);
1799 static const detail::Cycle cycle;
1801 static const detail::Dereference dereference;
1803 inline detail::Take take(size_t count) {
1804 return detail::Take(count);
1807 template<class Random = std::default_random_engine>
1808 inline detail::Sample<Random> sample(size_t count, Random rng = Random()) {
1809 return detail::Sample<Random>(count, std::move(rng));
1812 inline detail::Skip skip(size_t count) {
1813 return detail::Skip(count);
1816 inline detail::Batch batch(size_t batchSize) {
1817 return detail::Batch(batchSize);
1822 #pragma GCC diagnostic pop