2 * Copyright 2017 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 #include <folly/Portability.h>
23 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
25 FOLLY_GCC_DISABLE_WARNING("-Wshadow")
31 * ArgumentReference - For determining ideal argument type to receive a value.
34 struct ArgumentReference
35 : public std::conditional<
36 std::is_reference<T>::value,
37 T, // T& -> T&, T&& -> T&&, const T& -> const T&
38 typename std::conditional<std::is_const<T>::value,
39 T&, // const int -> const int&
44 * Group - The output objects from the GroupBy operator
46 template <class Key, class Value>
47 class Group : public GenImpl<Value&&, Group<Key, Value>> {
49 static_assert(!std::is_reference<Key>::value &&
50 !std::is_reference<Value>::value,
51 "Key and Value must be decayed types");
53 typedef std::vector<Value> VectorType;
55 typedef Value ValueType;
57 Group(Key key, VectorType values)
58 : key_(std::move(key)), values_(std::move(values)) {}
60 const Key& key() const { return key_; }
62 size_t size() const { return values_.size(); }
63 const VectorType& values() const { return values_; }
64 VectorType& values() { return values_; }
66 VectorType operator|(const detail::Collect<VectorType>&) const {
70 VectorType operator|(const detail::CollectTemplate<std::vector>&) const {
75 void foreach(Body&& body) const {
76 for (auto& value : values_) {
77 body(std::move(value));
81 template <class Handler>
82 bool apply(Handler&& handler) const {
83 for (auto& value : values_) {
84 if (!handler(std::move(value))) {
91 // GroupBy only takes in finite generators, so we only have finite groups
92 static constexpr bool infinite = false;
96 mutable VectorType values_;
101 // Classes used for the implementation of Sources, Operators, and Sinks
104 ******************************* Sources ***************************************
108 * ReferencedSource - Generate values from an STL-like container using
109 * iterators from .begin() until .end(). Value type defaults to the type of
110 * *container->begin(). For std::vector<int>, this would be int&. Note that the
111 * value here is a reference, so the values in the vector will be passed by
112 * reference to downstream operators.
114 * This type is primarily used through the 'from' helper method, like:
116 * string& longestName = from(names)
117 * | maxBy([](string& s) { return s.size() });
119 template <class Container, class Value>
120 class ReferencedSource
121 : public GenImpl<Value, ReferencedSource<Container, Value>> {
122 Container* container_;
125 explicit ReferencedSource(Container* container) : container_(container) {}
127 template <class Body>
128 void foreach(Body&& body) const {
129 for (auto& value : *container_) {
130 body(std::forward<Value>(value));
134 template <class Handler>
135 bool apply(Handler&& handler) const {
136 for (auto& value : *container_) {
137 if (!handler(std::forward<Value>(value))) {
144 // from takes in a normal stl structure, which are all finite
145 static constexpr bool infinite = false;
149 * CopiedSource - For producing values from eagerly from a sequence of values
150 * whose storage is owned by this class. Useful for preparing a generator for
151 * use after a source collection will no longer be available, or for when the
152 * values are specified literally with an initializer list.
154 * This type is primarily used through the 'fromCopy' function, like:
156 * auto sourceCopy = fromCopy(makeAVector());
157 * auto sum = sourceCopy | sum;
158 * auto max = sourceCopy | max;
160 * Though it is also used for the initializer_list specialization of from().
162 template <class StorageType, class Container>
164 : public GenImpl<const StorageType&, CopiedSource<StorageType, Container>> {
165 static_assert(!std::is_reference<StorageType>::value,
166 "StorageType must be decayed");
169 // Generator objects are often copied during normal construction as they are
170 // encapsulated by downstream generators. It would be bad if this caused
171 // a copy of the entire container each time, and since we're only exposing a
172 // const reference to the value, it's safe to share it between multiple
174 static_assert(!std::is_reference<Container>::value,
175 "Can't copy into a reference");
176 std::shared_ptr<const Container> copy_;
179 typedef Container ContainerType;
181 template <class SourceContainer>
182 explicit CopiedSource(const SourceContainer& container)
183 : copy_(new Container(begin(container), end(container))) {}
185 explicit CopiedSource(Container&& container)
186 : copy_(new Container(std::move(container))) {}
188 // To enable re-use of cached results.
189 CopiedSource(const CopiedSource<StorageType, Container>& source)
190 : copy_(source.copy_) {}
192 template <class Body>
193 void foreach(Body&& body) const {
194 for (const auto& value : *copy_) {
199 template <class Handler>
200 bool apply(Handler&& handler) const {
201 // The collection may be reused by others, we can't allow it to be changed.
202 for (const auto& value : *copy_) {
203 if (!handler(value)) {
210 // from takes in a normal stl structure, which are all finite
211 static constexpr bool infinite = false;
215 * RangeSource - For producing values from a folly::Range. Useful for referring
216 * to a slice of some container.
218 * This type is primarily used through the 'from' function, like:
220 * auto rangeSource = from(folly::range(v.begin(), v.end()));
221 * auto sum = rangeSource | sum;
223 * Reminder: Be careful not to invalidate iterators when using ranges like this.
225 template <class Iterator>
226 class RangeSource : public GenImpl<typename Range<Iterator>::reference,
227 RangeSource<Iterator>> {
228 Range<Iterator> range_;
231 RangeSource() = default;
232 explicit RangeSource(Range<Iterator> range) : range_(std::move(range)) {}
234 template <class Handler>
235 bool apply(Handler&& handler) const {
236 for (auto& value : range_) {
237 if (!handler(value)) {
244 template <class Body>
245 void foreach(Body&& body) const {
246 for (auto& value : range_) {
251 // folly::Range only supports finite ranges
252 static constexpr bool infinite = false;
256 * Sequence - For generating values from beginning value, incremented along the
257 * way with the ++ and += operators. Iteration may continue indefinitely.
258 * Value type specified explicitly.
260 * This type is primarily used through the 'seq' and 'range' function, like:
262 * int total = seq(1, 10) | sum;
263 * auto indexes = range(0, 10);
264 * auto endless = seq(0); // 0, 1, 2, 3, ...
266 template <class Value, class SequenceImpl>
267 class Sequence : public GenImpl<const Value&, Sequence<Value, SequenceImpl>> {
268 static_assert(!std::is_reference<Value>::value &&
269 !std::is_const<Value>::value,
270 "Value mustn't be const or ref.");
275 explicit Sequence(Value start, SequenceImpl impl)
276 : start_(std::move(start)), impl_(std::move(impl)) {}
278 template <class Handler>
279 bool apply(Handler&& handler) const {
280 for (Value current = start_; impl_.test(current); impl_.step(current)) {
281 if (!handler(current)) {
288 template <class Body>
289 void foreach(Body&& body) const {
290 for (Value current = start_; impl_.test(current); impl_.step(current)) {
295 // Let the implementation say if we are infinite or not
296 static constexpr bool infinite = SequenceImpl::infinite;
300 * Sequence implementations (range, sequence, infinite, with/without step)
302 template <class Value>
307 explicit RangeImpl(Value end) : end_(std::move(end)) {}
308 bool test(const Value& current) const { return current < end_; }
309 void step(Value& current) const { ++current; }
310 static constexpr bool infinite = false;
313 template <class Value, class Distance>
314 class RangeWithStepImpl {
319 explicit RangeWithStepImpl(Value end, Distance step)
320 : end_(std::move(end)), step_(std::move(step)) {}
321 bool test(const Value& current) const { return current < end_; }
322 void step(Value& current) const { current += step_; }
323 static constexpr bool infinite = false;
326 template <class Value>
331 explicit SeqImpl(Value end) : end_(std::move(end)) {}
332 bool test(const Value& current) const { return current <= end_; }
333 void step(Value& current) const { ++current; }
334 static constexpr bool infinite = false;
337 template <class Value, class Distance>
338 class SeqWithStepImpl {
343 explicit SeqWithStepImpl(Value end, Distance step)
344 : end_(std::move(end)), step_(std::move(step)) {}
345 bool test(const Value& current) const { return current <= end_; }
346 void step(Value& current) const { current += step_; }
347 static constexpr bool infinite = false;
350 template <class Value>
353 bool test(const Value& /* current */) const { return true; }
354 void step(Value& current) const { ++current; }
355 static constexpr bool infinite = true;
359 * GenratorBuilder - Helper for GENERTATOR macro.
361 template <class Value>
362 struct GeneratorBuilder {
363 template <class Source, class Yield = detail::Yield<Value, Source>>
364 Yield operator+(Source&& source) {
365 return Yield(std::forward<Source>(source));
370 * Yield - For producing values from a user-defined generator by way of a
373 template <class Value, class Source>
374 class Yield : public GenImpl<Value, Yield<Value, Source>> {
378 explicit Yield(Source source) : source_(std::move(source)) {}
380 template <class Handler>
381 bool apply(Handler&& handler) const {
383 auto body = [&](Value value) {
384 if (!handler(std::forward<Value>(value))) {
396 template <class Body>
397 void foreach(Body&& body) const {
398 source_(std::forward<Body>(body));
402 template <class Value>
403 class Empty : public GenImpl<Value, Empty<Value>> {
405 template <class Handler>
406 bool apply(Handler&&) const {
410 template <class Body>
411 void foreach(Body&&) const {}
413 // No values, so finite
414 static constexpr bool infinite = false;
417 template <class Value>
418 class SingleReference : public GenImpl<Value&, SingleReference<Value>> {
419 static_assert(!std::is_reference<Value>::value,
420 "SingleReference requires non-ref types");
424 explicit SingleReference(Value& ref) : ptr_(&ref) {}
426 template <class Handler>
427 bool apply(Handler&& handler) const {
428 return handler(*ptr_);
431 template <class Body>
432 void foreach(Body&& body) const {
436 // One value, so finite
437 static constexpr bool infinite = false;
440 template <class Value>
441 class SingleCopy : public GenImpl<const Value&, SingleCopy<Value>> {
442 static_assert(!std::is_reference<Value>::value,
443 "SingleCopy requires non-ref types");
447 explicit SingleCopy(Value value) : value_(std::forward<Value>(value)) {}
449 template <class Handler>
450 bool apply(Handler&& handler) const {
451 return handler(value_);
454 template <class Body>
455 void foreach(Body&& body) const {
459 // One value, so finite
460 static constexpr bool infinite = false;
464 ***************************** Operators ***************************************
468 * Map - For producing a sequence of values by passing each value from a source
469 * collection through a predicate.
471 * This type is usually used through the 'map' or 'mapped' helper function:
473 * auto squares = seq(1, 10) | map(square) | asVector;
475 template <class Predicate>
476 class Map : public Operator<Map<Predicate>> {
482 explicit Map(Predicate pred) : pred_(std::move(pred)) {}
487 class Result = typename ArgumentReference<
488 typename std::result_of<Predicate(Value)>::type>::type>
489 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
494 explicit Generator(Source source, const Predicate& pred)
495 : source_(std::move(source)), pred_(pred) {}
497 template <class Body>
498 void foreach(Body&& body) const {
500 [&](Value value) { body(pred_(std::forward<Value>(value))); });
503 template <class Handler>
504 bool apply(Handler&& handler) const {
505 return source_.apply([&](Value value) {
506 return handler(pred_(std::forward<Value>(value)));
510 static constexpr bool infinite = Source::infinite;
513 template <class Source, class Value, class Gen = Generator<Value, Source>>
514 Gen compose(GenImpl<Value, Source>&& source) const {
515 return Gen(std::move(source.self()), pred_);
518 template <class Source, class Value, class Gen = Generator<Value, Source>>
519 Gen compose(const GenImpl<Value, Source>& source) const {
520 return Gen(source.self(), pred_);
525 * Filter - For filtering values from a source sequence by a predicate.
527 * This type is usually used through the 'filter' helper function, like:
529 * auto nonEmpty = from(strings)
530 * | filter([](const string& str) -> bool {
531 * return !str.empty();
534 * Note that if no predicate is provided, the values are casted to bool and
535 * filtered based on that. So if pointers is a vector of pointers,
537 * auto nonNull = from(pointers) | filter();
539 * will give a vector of all the pointers != nullptr.
541 template <class Predicate>
542 class Filter : public Operator<Filter<Predicate>> {
547 explicit Filter(Predicate pred) : pred_(std::move(pred)) {}
549 template <class Value, class Source>
550 class Generator : public GenImpl<Value, Generator<Value, Source>> {
555 explicit Generator(Source source, const Predicate& pred)
556 : source_(std::move(source)), pred_(pred) {}
558 template <class Body>
559 void foreach(Body&& body) const {
560 source_.foreach([&](Value value) {
561 // NB: Argument not forwarded to avoid accidental move-construction
563 body(std::forward<Value>(value));
568 template <class Handler>
569 bool apply(Handler&& handler) const {
570 return source_.apply([&](Value value) -> bool {
571 // NB: Argument not forwarded to avoid accidental move-construction
573 return handler(std::forward<Value>(value));
579 static constexpr bool infinite = Source::infinite;
582 template <class Source, class Value, class Gen = Generator<Value, Source>>
583 Gen compose(GenImpl<Value, Source>&& source) const {
584 return Gen(std::move(source.self()), pred_);
587 template <class Source, class Value, class Gen = Generator<Value, Source>>
588 Gen compose(const GenImpl<Value, Source>& source) const {
589 return Gen(source.self(), pred_);
594 * Until - For producing values from a source until a predicate is satisfied.
596 * This type is usually used through the 'until' helper function, like:
598 * auto best = from(sortedItems)
599 * | until([](Item& item) { return item.score > 100; })
602 template <class Predicate>
603 class Until : public Operator<Until<Predicate>> {
608 explicit Until(Predicate pred) : pred_(std::move(pred)) {}
610 template <class Value, class Source>
611 class Generator : public GenImpl<Value, Generator<Value, Source>> {
616 explicit Generator(Source source, const Predicate& pred)
617 : source_(std::move(source)), pred_(pred) {}
619 template <class Handler>
620 bool apply(Handler&& handler) const {
621 bool cancelled = false;
622 source_.apply([&](Value value) -> bool {
623 if (pred_(value)) { // un-forwarded to disable move
626 if (!handler(std::forward<Value>(value))) {
635 // Theoretically an 'until' might stop an infinite
636 static constexpr bool infinite = false;
639 template <class Source, class Value, class Gen = Generator<Value, Source>>
640 Gen compose(GenImpl<Value, Source>&& source) const {
641 return Gen(std::move(source.self()), pred_);
644 template <class Source, class Value, class Gen = Generator<Value, Source>>
645 Gen compose(const GenImpl<Value, Source>& source) const {
646 return Gen(source.self(), pred_);
651 * Take - For producing up to N values from a source.
653 * This type is usually used through the 'take' helper function, like:
655 * auto best = from(docs)
656 * | orderByDescending(scoreDoc)
659 class Take : public Operator<Take> {
663 explicit Take(size_t count) : count_(count) {}
665 template <class Value, class Source>
666 class Generator : public GenImpl<Value, Generator<Value, Source>> {
671 explicit Generator(Source source, size_t count)
672 : source_(std::move(source)), count_(count) {}
674 template <class Handler>
675 bool apply(Handler&& handler) const {
680 bool cancelled = false;
681 source_.apply([&](Value value) -> bool {
682 if (!handler(std::forward<Value>(value))) {
691 // take will stop an infinite generator
692 static constexpr bool infinite = false;
695 template <class Source, class Value, class Gen = Generator<Value, Source>>
696 Gen compose(GenImpl<Value, Source>&& source) const {
697 return Gen(std::move(source.self()), count_);
700 template <class Source, class Value, class Gen = Generator<Value, Source>>
701 Gen compose(const GenImpl<Value, Source>& source) const {
702 return Gen(source.self(), count_);
707 * Stride - For producing every Nth value from a source.
709 * This type is usually used through the 'stride' helper function, like:
711 * auto half = from(samples)
714 class Stride : public Operator<Stride> {
718 explicit Stride(size_t stride) : stride_(stride) {
720 throw std::invalid_argument("stride must not be 0");
724 template <class Value, class Source>
725 class Generator : public GenImpl<Value, Generator<Value, Source>> {
730 explicit Generator(Source source, size_t stride)
731 : source_(std::move(source)), stride_(stride) {}
733 template <class Handler>
734 bool apply(Handler&& handler) const {
735 size_t distance = stride_;
736 return source_.apply([&](Value value) -> bool {
737 if (++distance >= stride_) {
738 if (!handler(std::forward<Value>(value))) {
747 template <class Body>
748 void foreach(Body&& body) const {
749 size_t distance = stride_;
750 source_.foreach([&](Value value) {
751 if (++distance >= stride_) {
752 body(std::forward<Value>(value));
758 // Taking every Nth of an infinite list is still infinte
759 static constexpr bool infinite = Source::infinite;
762 template <class Source, class Value, class Gen = Generator<Value, Source>>
763 Gen compose(GenImpl<Value, Source>&& source) const {
764 return Gen(std::move(source.self()), stride_);
767 template <class Source, class Value, class Gen = Generator<Value, Source>>
768 Gen compose(const GenImpl<Value, Source>& source) const {
769 return Gen(source.self(), stride_);
774 * Sample - For taking a random sample of N elements from a sequence
775 * (without replacement).
777 template <class Random>
778 class Sample : public Operator<Sample<Random>> {
783 explicit Sample(size_t count, Random rng)
784 : count_(count), rng_(std::move(rng)) {}
790 class StorageType = typename std::decay<Value>::type>
792 : public GenImpl<StorageType&&,
793 Generator<Value, Source, Rand, StorageType>> {
794 static_assert(!Source::infinite, "Cannot sample infinite source!");
795 // It's too easy to bite ourselves if random generator is only 16-bit
796 static_assert(Random::max() >= std::numeric_limits<int32_t>::max() - 1,
797 "Random number generator must support big values");
803 explicit Generator(Source source, size_t count, Random rng)
804 : source_(std::move(source)), count_(count), rng_(std::move(rng)) {}
806 template <class Handler>
807 bool apply(Handler&& handler) const {
811 std::vector<StorageType> v;
813 // use reservoir sampling to give each source value an equal chance
814 // of appearing in our output.
816 source_.foreach([&](Value value) -> void {
817 if (v.size() < count_) {
818 v.push_back(std::forward<Value>(value));
820 // alternatively, we could create a std::uniform_int_distribution
821 // instead of using modulus, but benchmarks show this has
822 // substantial overhead.
823 size_t index = rng_() % n;
824 if (index < v.size()) {
825 v[index] = std::forward<Value>(value);
831 // output is unsorted!
832 for (auto& val : v) {
833 if (!handler(std::move(val))) {
840 // Only takes N elements, so finite
841 static constexpr bool infinite = false;
847 class Gen = Generator<Value, Source, Random>>
848 Gen compose(GenImpl<Value, Source>&& source) const {
849 return Gen(std::move(source.self()), count_, rng_);
855 class Gen = Generator<Value, Source, Random>>
856 Gen compose(const GenImpl<Value, Source>& source) const {
857 return Gen(source.self(), count_, rng_);
862 * Skip - For skipping N items from the beginning of a source generator.
864 * This type is usually used through the 'skip' helper function, like:
866 * auto page = from(results)
867 * | skip(pageSize * startPage)
870 class Skip : public Operator<Skip> {
874 explicit Skip(size_t count) : count_(count) {}
876 template <class Value, class Source>
877 class Generator : public GenImpl<Value, Generator<Value, Source>> {
882 explicit Generator(Source source, size_t count)
883 : source_(std::move(source)), count_(count) {}
885 template <class Body>
886 void foreach(Body&& body) const {
888 source_.foreach(body);
892 source_.foreach([&](Value value) {
896 body(std::forward<Value>(value));
901 template <class Handler>
902 bool apply(Handler&& handler) const {
904 return source_.apply(std::forward<Handler>(handler));
907 return source_.apply([&](Value value) -> bool {
912 return handler(std::forward<Value>(value));
916 // Skipping N items of an infinite source is still infinite
917 static constexpr bool infinite = Source::infinite;
920 template <class Source, class Value, class Gen = Generator<Value, Source>>
921 Gen compose(GenImpl<Value, Source>&& source) const {
922 return Gen(std::move(source.self()), count_);
925 template <class Source, class Value, class Gen = Generator<Value, Source>>
926 Gen compose(const GenImpl<Value, Source>& source) const {
927 return Gen(source.self(), count_);
932 * Order - For ordering a sequence of values from a source by key.
933 * The key is extracted by the given selector functor, and this key is then
934 * compared using the specified comparator.
936 * This type is usually used through the 'order' helper function, like:
938 * auto closest = from(places)
939 * | orderBy([](Place& p) {
940 * return -distance(p.location, here);
944 template <class Selector, class Comparer>
945 class Order : public Operator<Order<Selector, Comparer>> {
952 explicit Order(Selector selector) : selector_(std::move(selector)) {}
954 Order(Selector selector, Comparer comparer)
955 : selector_(std::move(selector)), comparer_(std::move(comparer)) {}
960 class StorageType = typename std::decay<Value>::type,
961 class Result = typename std::result_of<Selector(Value)>::type>
963 : public GenImpl<StorageType&&,
964 Generator<Value, Source, StorageType, Result>> {
965 static_assert(!Source::infinite, "Cannot sort infinite source!");
970 typedef std::vector<StorageType> VectorType;
972 VectorType asVector() const {
973 auto comparer = [&](const StorageType& a, const StorageType& b) {
974 return comparer_(selector_(a), selector_(b));
976 auto vals = source_ | as<VectorType>();
977 std::sort(vals.begin(), vals.end(), comparer);
978 return std::move(vals);
982 Generator(Source source, Selector selector, Comparer comparer)
983 : source_(std::move(source)),
984 selector_(std::move(selector)),
985 comparer_(std::move(comparer)) {}
987 VectorType operator|(const Collect<VectorType>&) const {
991 VectorType operator|(const CollectTemplate<std::vector>&) const {
995 template <class Body>
996 void foreach(Body&& body) const {
997 for (auto& value : asVector()) {
998 body(std::move(value));
1002 template <class Handler>
1003 bool apply(Handler&& handler) const {
1004 auto comparer = [&](const StorageType& a, const StorageType& b) {
1005 // swapped for minHeap
1006 return comparer_(selector_(b), selector_(a));
1008 auto heap = source_ | as<VectorType>();
1009 std::make_heap(heap.begin(), heap.end(), comparer);
1010 while (!heap.empty()) {
1011 std::pop_heap(heap.begin(), heap.end(), comparer);
1012 if (!handler(std::move(heap.back()))) {
1020 // Can only be run on and produce finite generators
1021 static constexpr bool infinite = false;
1024 template <class Source, class Value, class Gen = Generator<Value, Source>>
1025 Gen compose(GenImpl<Value, Source>&& source) const {
1026 return Gen(std::move(source.self()), selector_, comparer_);
1029 template <class Source, class Value, class Gen = Generator<Value, Source>>
1030 Gen compose(const GenImpl<Value, Source>& source) const {
1031 return Gen(source.self(), selector_, comparer_);
1036 * GroupBy - Group values by a given key selector, producing a sequence of
1039 * This type is usually used through the 'groupBy' helper function, like:
1043 * | groupBy([](const Place& p) {
1046 * | [](Group<std::string, Place>&& g) {
1047 * cout << g.key() << ": " << (g | first).description;
1050 template <class Selector>
1051 class GroupBy : public Operator<GroupBy<Selector>> {
1057 explicit GroupBy(Selector selector) : selector_(std::move(selector)) {}
1062 class ValueDecayed = typename std::decay<Value>::type,
1063 class Key = typename std::result_of<Selector(Value)>::type,
1064 class KeyDecayed = typename std::decay<Key>::type>
1067 Group<KeyDecayed, ValueDecayed>&&,
1068 Generator<Value, Source, ValueDecayed, Key, KeyDecayed>> {
1069 static_assert(!Source::infinite, "Cannot group infinite source!");
1074 Generator(Source source, Selector selector)
1075 : source_(std::move(source)), selector_(std::move(selector)) {}
1077 typedef Group<KeyDecayed, ValueDecayed> GroupType;
1079 template <class Handler>
1080 bool apply(Handler&& handler) const {
1081 std::unordered_map<KeyDecayed, typename GroupType::VectorType> groups;
1082 source_ | [&](Value value) {
1083 const Value& cv = value;
1084 auto& group = groups[selector_(cv)];
1085 group.push_back(std::forward<Value>(value));
1087 for (auto& kg : groups) {
1088 GroupType group(kg.first, std::move(kg.second));
1089 if (!handler(std::move(group))) {
1097 // Can only be run on and produce finite generators
1098 static constexpr bool infinite = false;
1101 template <class Source, class Value, class Gen = Generator<Value, Source>>
1102 Gen compose(GenImpl<Value, Source>&& source) const {
1103 return Gen(std::move(source.self()), selector_);
1106 template <class Source, class Value, class Gen = Generator<Value, Source>>
1107 Gen compose(const GenImpl<Value, Source>& source) const {
1108 return Gen(source.self(), selector_);
1113 * TypeAssertion - For verifying the exact type of the value produced by a
1114 * generator. Useful for testing and debugging, and acts as a no-op at runtime.
1115 * Pass-through at runtime. Used through the 'assert_type<>()' factory method
1118 * auto c = from(vector) | assert_type<int&>() | sum;
1121 template <class Expected>
1122 class TypeAssertion : public Operator<TypeAssertion<Expected>> {
1124 template <class Source, class Value>
1125 const Source& compose(const GenImpl<Value, Source>& source) const {
1126 static_assert(std::is_same<Expected, Value>::value,
1127 "assert_type() check failed");
1128 return source.self();
1131 template <class Source, class Value>
1132 Source&& compose(GenImpl<Value, Source>&& source) const {
1133 static_assert(std::is_same<Expected, Value>::value,
1134 "assert_type() check failed");
1135 return std::move(source.self());
1140 * Distinct - For filtering duplicates out of a sequence. A selector may be
1141 * provided to generate a key to uniquify for each value.
1143 * This type is usually used through the 'distinct' helper function, like:
1145 * auto closest = from(results)
1146 * | distinctBy([](Item& i) {
1151 template <class Selector>
1152 class Distinct : public Operator<Distinct<Selector>> {
1156 Distinct() = default;
1158 explicit Distinct(Selector selector) : selector_(std::move(selector)) {}
1160 template <class Value, class Source>
1161 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1165 typedef typename std::decay<Value>::type StorageType;
1167 // selector_ cannot be passed an rvalue or it would end up passing the husk
1168 // of a value to the downstream operators.
1169 typedef const StorageType& ParamType;
1171 typedef typename std::result_of<Selector(ParamType)>::type KeyType;
1172 typedef typename std::decay<KeyType>::type KeyStorageType;
1175 Generator(Source source, Selector selector)
1176 : source_(std::move(source)), selector_(std::move(selector)) {}
1178 template <class Body>
1179 void foreach(Body&& body) const {
1180 std::unordered_set<KeyStorageType> keysSeen;
1181 source_.foreach([&](Value value) {
1182 if (keysSeen.insert(selector_(ParamType(value))).second) {
1183 body(std::forward<Value>(value));
1188 template <class Handler>
1189 bool apply(Handler&& handler) const {
1190 std::unordered_set<KeyStorageType> keysSeen;
1191 return source_.apply([&](Value value) -> bool {
1192 if (keysSeen.insert(selector_(ParamType(value))).second) {
1193 return handler(std::forward<Value>(value));
1199 // While running distinct on an infinite sequence might produce a
1200 // conceptually finite sequence, it will take infinite time
1201 static constexpr bool infinite = Source::infinite;
1204 template <class Source, class Value, class Gen = Generator<Value, Source>>
1205 Gen compose(GenImpl<Value, Source>&& source) const {
1206 return Gen(std::move(source.self()), selector_);
1209 template <class Source, class Value, class Gen = Generator<Value, Source>>
1210 Gen compose(const GenImpl<Value, Source>& source) const {
1211 return Gen(source.self(), selector_);
1216 * Composer - Helper class for adapting pipelines into functors. Primarily used
1219 template <class Operators>
1224 explicit Composer(Operators op) : op_(std::move(op)) {}
1229 decltype(std::declval<Operators>().compose(std::declval<Source>()))>
1230 Ret operator()(Source&& source) const {
1231 return op_.compose(std::forward<Source>(source));
1236 * Batch - For producing fixed-size batches of each value from a source.
1238 * This type is usually used through the 'batch' helper function:
1243 * | map([](const std::vector<int>& batch) {
1244 * return from(batch) | sum;
1248 class Batch : public Operator<Batch> {
1252 explicit Batch(size_t batchSize) : batchSize_(batchSize) {
1253 if (batchSize_ == 0) {
1254 throw std::invalid_argument("Batch size must be non-zero!");
1261 class StorageType = typename std::decay<Value>::type,
1262 class VectorType = std::vector<StorageType>>
1264 : public GenImpl<VectorType&,
1265 Generator<Value, Source, StorageType, VectorType>> {
1270 explicit Generator(Source source, size_t batchSize)
1271 : source_(std::move(source)), batchSize_(batchSize) {}
1273 template <class Handler>
1274 bool apply(Handler&& handler) const {
1276 batch_.reserve(batchSize_);
1277 bool shouldContinue = source_.apply([&](Value value) -> bool {
1278 batch_.push_back(std::forward<Value>(value));
1279 if (batch_.size() == batchSize_) {
1280 bool needMore = handler(batch_);
1284 // Always need more if the handler is not called.
1287 // Flush everything, if and only if `handler` hasn't returned false.
1288 if (shouldContinue && !batch_.empty()) {
1289 shouldContinue = handler(batch_);
1292 return shouldContinue;
1295 // Taking n-tuples of an infinite source is still infinite
1296 static constexpr bool infinite = Source::infinite;
1299 template <class Source, class Value, class Gen = Generator<Value, Source>>
1300 Gen compose(GenImpl<Value, Source>&& source) const {
1301 return Gen(std::move(source.self()), batchSize_);
1304 template <class Source, class Value, class Gen = Generator<Value, Source>>
1305 Gen compose(const GenImpl<Value, Source>& source) const {
1306 return Gen(source.self(), batchSize_);
1311 * Concat - For flattening generators of generators.
1313 * This type is usually used through the 'concat' static value, like:
1317 * | map([](Node& x) {
1318 * return from(x.neighbors)
1319 * | map([&](Node& y) {
1320 * return Edge(x, y);
1326 class Concat : public Operator<Concat> {
1333 class InnerValue = typename std::decay<Inner>::type::ValueType>
1335 : public GenImpl<InnerValue, Generator<Inner, Source, InnerValue>> {
1339 explicit Generator(Source source) : source_(std::move(source)) {}
1341 template <class Handler>
1342 bool apply(Handler&& handler) const {
1343 return source_.apply([&](Inner inner) -> bool {
1344 return inner.apply(std::forward<Handler>(handler));
1348 template <class Body>
1349 void foreach(Body&& body) const {
1350 source_.foreach([&](Inner inner) {
1351 inner.foreach(std::forward<Body>(body));
1355 // Resulting concatination is only finite if both Source and Inner are also
1356 // finite. In one sence, if dosn't make sence to call concat when the Inner
1357 // generator is infinite (you could just call first), so we could also just
1358 // static_assert if the inner is infinite. Taking the less restrictive
1360 static constexpr bool infinite =
1361 Source::infinite || std::decay<Inner>::type::infinite;
1364 template <class Value, class Source, class Gen = Generator<Value, Source>>
1365 Gen compose(GenImpl<Value, Source>&& source) const {
1366 return Gen(std::move(source.self()));
1369 template <class Value, class Source, class Gen = Generator<Value, Source>>
1370 Gen compose(const GenImpl<Value, Source>& source) const {
1371 return Gen(source.self());
1376 * RangeConcat - For flattening generators of iterables.
1378 * This type is usually used through the 'rconcat' static value, like:
1380 * map<int, vector<int>> adjacency;
1387 class RangeConcat : public Operator<RangeConcat> {
1389 RangeConcat() = default;
1394 class InnerValue = typename ValueTypeOfRange<Range>::RefType>
1396 : public GenImpl<InnerValue, Generator<Range, Source, InnerValue>> {
1400 explicit Generator(Source source) : source_(std::move(source)) {}
1402 template <class Body>
1403 void foreach(Body&& body) const {
1404 source_.foreach([&](Range range) {
1405 for (auto& value : range) {
1411 template <class Handler>
1412 bool apply(Handler&& handler) const {
1413 return source_.apply([&](Range range) -> bool {
1414 for (auto& value : range) {
1415 if (!handler(value)) {
1423 // This is similar to concat, except that the inner iterables all are finite
1424 // so the only thing that matters is that the source is infinite.
1425 static constexpr bool infinite = Source::infinite;
1428 template <class Value, class Source, class Gen = Generator<Value, Source>>
1429 Gen compose(GenImpl<Value, Source>&& source) const {
1430 return Gen(std::move(source.self()));
1433 template <class Value, class Source, class Gen = Generator<Value, Source>>
1434 Gen compose(const GenImpl<Value, Source>& source) const {
1435 return Gen(source.self());
1440 * GuardImpl - For handling exceptions from downstream computation. Requires the
1441 * type of exception to catch, and handler function to invoke in the event of
1442 * the exception. Note that the handler may:
1443 * 1) return true to continue processing the sequence
1444 * 2) return false to end the sequence immediately
1445 * 3) throw, to pass the exception to the next catch
1446 * The handler must match the signature 'bool(Exception&, Value)'.
1448 * This type is used through the `guard` helper, like so:
1451 * = byLine(STDIN_FILENO)
1452 * | guard<std::runtime_error>([](std::runtime_error& e,
1454 * LOG(ERROR) << sp << ": " << e.str();
1455 * return true; // continue processing subsequent lines
1460 * TODO(tjackson): Rename this back to Guard.
1462 template <class Exception, class ErrorHandler>
1463 class GuardImpl : public Operator<GuardImpl<Exception, ErrorHandler>> {
1464 ErrorHandler handler_;
1467 explicit GuardImpl(ErrorHandler handler) : handler_(std::move(handler)) {}
1469 template <class Value, class Source>
1470 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1472 ErrorHandler handler_;
1475 explicit Generator(Source source, ErrorHandler handler)
1476 : source_(std::move(source)), handler_(std::move(handler)) {}
1478 template <class Handler>
1479 bool apply(Handler&& handler) const {
1480 return source_.apply([&](Value value) -> bool {
1482 handler(std::forward<Value>(value));
1484 } catch (Exception& e) {
1485 return handler_(e, std::forward<Value>(value));
1490 // Just passes value though, length unaffected
1491 static constexpr bool infinite = Source::infinite;
1494 template <class Value, class Source, class Gen = Generator<Value, Source>>
1495 Gen compose(GenImpl<Value, Source>&& source) const {
1496 return Gen(std::move(source.self()), handler_);
1499 template <class Value, class Source, class Gen = Generator<Value, Source>>
1500 Gen compose(const GenImpl<Value, Source>& source) const {
1501 return Gen(source.self(), handler_);
1506 * Dereference - For dereferencing a sequence of pointers while filtering out
1509 * This type is usually used through the 'dereference' static value, like:
1511 * auto refs = from(ptrs) | dereference;
1513 class Dereference : public Operator<Dereference> {
1515 Dereference() = default;
1520 class Result = decltype(*std::declval<Value>())>
1521 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
1525 explicit Generator(Source source) : source_(std::move(source)) {}
1527 template <class Body>
1528 void foreach(Body&& body) const {
1529 source_.foreach([&](Value value) {
1531 return body(*std::forward<Value>(value));
1536 template <class Handler>
1537 bool apply(Handler&& handler) const {
1538 return source_.apply([&](Value value) -> bool {
1540 return handler(*std::forward<Value>(value));
1546 // Just passes value though, length unaffected
1547 static constexpr bool infinite = Source::infinite;
1550 template <class Source, class Value, class Gen = Generator<Value, Source>>
1551 Gen compose(GenImpl<Value, Source>&& source) const {
1552 return Gen(std::move(source.self()));
1555 template <class Source, class Value, class Gen = Generator<Value, Source>>
1556 Gen compose(const GenImpl<Value, Source>& source) const {
1557 return Gen(source.self());
1562 * Indirect - For producing a sequence of the addresses of the values in the
1565 * This type is usually used through the 'indirect' static value, like:
1567 * auto ptrs = from(refs) | indirect;
1569 class Indirect : public Operator<Indirect> {
1571 Indirect() = default;
1576 class Result = typename std::remove_reference<Value>::type*>
1577 class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
1579 static_assert(!std::is_rvalue_reference<Value>::value,
1580 "Cannot use indirect on an rvalue");
1583 explicit Generator(Source source) : source_(std::move(source)) {}
1585 template <class Body>
1586 void foreach(Body&& body) const {
1587 source_.foreach([&](Value value) {
1588 return body(&std::forward<Value>(value));
1592 template <class Handler>
1593 bool apply(Handler&& handler) const {
1594 return source_.apply([&](Value value) -> bool {
1595 return handler(&std::forward<Value>(value));
1599 // Just passes value though, length unaffected
1600 static constexpr bool infinite = Source::infinite;
1603 template <class Source, class Value, class Gen = Generator<Value, Source>>
1604 Gen compose(GenImpl<Value, Source>&& source) const {
1605 return Gen(std::move(source.self()));
1608 template <class Source, class Value, class Gen = Generator<Value, Source>>
1609 Gen compose(const GenImpl<Value, Source>& source) const {
1610 return Gen(source.self());
1615 * Cycle - For repeating a sequence forever.
1617 * This type is usually used through the 'cycle' static value, like:
1624 * or in the finite case:
1626 * auto thrice = g | cycle(3);
1628 template <bool forever>
1629 class Cycle : public Operator<Cycle<forever>> {
1630 off_t limit_; // not used if forever == true
1634 explicit Cycle(off_t limit) : limit_(limit) {
1637 "Cycle limit constructor should not be used when forever == true.");
1640 template <class Value, class Source>
1641 class Generator : public GenImpl<Value, Generator<Value, Source>> {
1646 explicit Generator(Source source, off_t limit)
1647 : source_(std::move(source)), limit_(limit) {}
1649 template <class Handler>
1650 bool apply(Handler&& handler) const {
1652 auto handler2 = [&](Value value) {
1653 cont = handler(std::forward<Value>(value));
1656 // Becomes an infinte loop if forever == true
1657 for (off_t count = 0; (forever || count != limit_); ++count) {
1659 source_.apply(handler2);
1667 // This is the hardest one to infer. If we are simply doing a finite cycle,
1668 // then (gen | cycle(n)) is infinite if and only if gen is infinite.
1669 // However, if we are doing an infinite cycle, (gen | cycle) is infinite
1670 // unless gen is empty. However, we will always mark (gen | cycle) as
1671 // infinite, because patterns such as (gen | cycle | count) can either take
1672 // on exactly one value, or infinite loop.
1673 static constexpr bool infinite = forever || Source::infinite;
1676 template <class Source, class Value, class Gen = Generator<Value, Source>>
1677 Gen compose(GenImpl<Value, Source>&& source) const {
1678 return Gen(std::move(source.self()), limit_);
1681 template <class Source, class Value, class Gen = Generator<Value, Source>>
1682 Gen compose(const GenImpl<Value, Source>& source) const {
1683 return Gen(source.self(), limit_);
1687 * Convenience function for finite cycles used like:
1689 * auto tripled = gen | cycle(3);
1691 Cycle<false> operator()(off_t limit) const { return Cycle<false>(limit); }
1695 ******************************* Sinks *****************************************
1699 * FoldLeft - Left-associative functional fold. For producing an aggregate value
1700 * from a seed and a folder function. Useful for custom aggregators on a
1703 * This type is primarily used through the 'foldl' helper method, like:
1705 * double movingAverage = from(values)
1706 * | foldl(0.0, [](double avg, double sample) {
1707 * return sample * 0.1 + avg * 0.9;
1710 template <class Seed, class Fold>
1711 class FoldLeft : public Operator<FoldLeft<Seed, Fold>> {
1716 FoldLeft() = default;
1717 FoldLeft(Seed seed, Fold fold)
1718 : seed_(std::move(seed)), fold_(std::move(fold)) {}
1720 template <class Source, class Value>
1721 Seed compose(const GenImpl<Value, Source>& source) const {
1722 static_assert(!Source::infinite, "Cannot foldl infinite source");
1724 source | [&](Value v) {
1725 accum = fold_(std::move(accum), std::forward<Value>(v));
1732 * First - For finding the first value in a sequence.
1734 * This type is primarily used through the 'first' static value, like:
1736 * int firstThreeDigitPrime = seq(100) | filter(isPrime) | first;
1738 class First : public Operator<First> {
1745 class StorageType = typename std::decay<Value>::type>
1746 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1747 Optional<StorageType> accum;
1748 source | [&](Value v) -> bool {
1749 accum = std::forward<Value>(v);
1757 * IsEmpty - a helper class for isEmpty and notEmpty
1759 * Essentially returns 'result' if the source is empty. Note that this cannot be
1760 * called on an infinite source, because then there is only one possible return
1764 * Used primarily through 'isEmpty' and 'notEmpty' static values
1766 * bool hasPrimes = g | filter(prime) | notEmpty;
1767 * bool lacksEvens = g | filter(even) | isEmpty;
1769 * Also used in the implementation of 'any' and 'all'
1771 template <bool emptyResult>
1772 class IsEmpty : public Operator<IsEmpty<emptyResult>> {
1774 IsEmpty() = default;
1776 template <class Source, class Value>
1777 bool compose(const GenImpl<Value, Source>& source) const {
1778 static_assert(!Source::infinite,
1779 "Cannot call 'all', 'any', 'isEmpty', or 'notEmpty' on "
1780 "infinite source. 'all' and 'isEmpty' will either return "
1781 "false or hang. 'any' or 'notEmpty' will either return true "
1783 bool ans = emptyResult;
1785 [&](Value /* v */) -> bool {
1794 * Reduce - Functional reduce, for recursively combining values from a source
1795 * using a reducer function until there is only one item left. Useful for
1796 * combining values when an empty sequence doesn't make sense.
1798 * This type is primarily used through the 'reduce' helper method, like:
1800 * sring longest = from(names)
1801 * | reduce([](string&& best, string& current) {
1802 * return best.size() >= current.size() ? best : current;
1805 template <class Reducer>
1806 class Reduce : public Operator<Reduce<Reducer>> {
1811 explicit Reduce(Reducer reducer) : reducer_(std::move(reducer)) {}
1816 class StorageType = typename std::decay<Value>::type>
1817 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1818 static_assert(!Source::infinite, "Cannot reduce infinite source");
1819 Optional<StorageType> accum;
1820 source | [&](Value v) {
1821 if (auto target = accum.get_pointer()) {
1822 *target = reducer_(std::move(*target), std::forward<Value>(v));
1824 accum = std::forward<Value>(v);
1832 * Count - for simply counting the items in a collection.
1834 * This type is usually used through its singleton, 'count':
1836 * auto shortPrimes = seq(1, 100) | filter(isPrime) | count;
1838 class Count : public Operator<Count> {
1842 template <class Source, class Value>
1843 size_t compose(const GenImpl<Value, Source>& source) const {
1844 static_assert(!Source::infinite, "Cannot count infinite source");
1845 return foldl(size_t(0),
1846 [](size_t accum, Value /* v */) { return accum + 1; })
1852 * Sum - For simply summing up all the values from a source.
1854 * This type is usually used through its singleton, 'sum':
1856 * auto gaussSum = seq(1, 100) | sum;
1858 class Sum : public Operator<Sum> {
1865 class StorageType = typename std::decay<Value>::type>
1866 StorageType compose(const GenImpl<Value, Source>& source) const {
1867 static_assert(!Source::infinite, "Cannot sum infinite source");
1868 return foldl(StorageType(0),
1869 [](StorageType&& accum, Value v) {
1870 return std::move(accum) + std::forward<Value>(v);
1876 * Contains - For testing whether a value matching the given value is contained
1879 * This type should be used through the 'contains' helper method, like:
1881 * bool contained = seq(1, 10) | map(square) | contains(49);
1883 template <class Needle>
1884 class Contains : public Operator<Contains<Needle>> {
1888 explicit Contains(Needle needle) : needle_(std::move(needle)) {}
1893 class StorageType = typename std::decay<Value>::type>
1894 bool compose(const GenImpl<Value, Source>& source) const {
1895 static_assert(!Source::infinite,
1896 "Calling contains on an infinite source might cause "
1897 "an infinite loop.");
1898 return !(source | [this](Value value) {
1899 return !(needle_ == std::forward<Value>(value));
1905 * Min - For a value which minimizes a key, where the key is determined by a
1906 * given selector, and compared by given comparer.
1908 * This type is usually used through the singletone 'min' or through the helper
1909 * functions 'minBy' and 'maxBy'.
1911 * auto oldest = from(people)
1912 * | minBy([](Person& p) {
1913 * return p.dateOfBirth;
1916 template <class Selector, class Comparer>
1917 class Min : public Operator<Min<Selector, Comparer>> {
1921 template <typename T>
1922 const T& asConst(const T& t) const {
1929 explicit Min(Selector selector) : selector_(std::move(selector)) {}
1931 Min(Selector selector, Comparer comparer)
1932 : selector_(std::move(selector)), comparer_(std::move(comparer)) {}
1937 class StorageType = typename std::decay<Value>::type,
1938 class Key = typename std::decay<
1939 typename std::result_of<Selector(Value)>::type>::type>
1940 Optional<StorageType> compose(const GenImpl<Value, Source>& source) const {
1941 static_assert(!Source::infinite,
1942 "Calling min or max on an infinite source will cause "
1943 "an infinite loop.");
1944 Optional<StorageType> min;
1945 Optional<Key> minKey;
1946 source | [&](Value v) {
1947 Key key = selector_(asConst(v)); // so that selector_ cannot mutate v
1948 if (auto lastKey = minKey.get_pointer()) {
1949 if (!comparer_(key, *lastKey)) {
1953 minKey = std::move(key);
1954 min = std::forward<Value>(v);
1961 * Append - For collecting values from a source into a given output container
1964 * This type is usually used through the helper function 'appendTo', like:
1966 * vector<int64_t> ids;
1967 * from(results) | map([](Person& p) { return p.id })
1970 template <class Collection>
1971 class Append : public Operator<Append<Collection>> {
1972 Collection* collection_;
1975 explicit Append(Collection* collection) : collection_(collection) {}
1977 template <class Value, class Source>
1978 Collection& compose(const GenImpl<Value, Source>& source) const {
1979 static_assert(!Source::infinite, "Cannot appendTo with infinite source");
1980 source | [&](Value v) {
1981 collection_->insert(collection_->end(), std::forward<Value>(v));
1983 return *collection_;
1988 * Collect - For collecting values from a source in a collection of the desired
1991 * This type is usually used through the helper function 'as', like:
1993 * std::string upper = from(stringPiece)
1995 * | as<std::string>();
1997 template <class Collection>
1998 class Collect : public Operator<Collect<Collection>> {
2000 Collect() = default;
2005 class StorageType = typename std::decay<Value>::type>
2006 Collection compose(const GenImpl<Value, Source>& source) const {
2007 static_assert(!Source::infinite,
2008 "Cannot convert infinite source to object with as.");
2009 Collection collection;
2010 source | [&](Value v) {
2011 collection.insert(collection.end(), std::forward<Value>(v));
2018 * CollectTemplate - For collecting values from a source in a collection
2019 * constructed using the specified template type. Given the type of values
2020 * produced by the given generator, the collection type will be:
2021 * Container<Value, Allocator<Value>>
2023 * The allocator defaults to std::allocator, so this may be used for the STL
2024 * containers by simply using operators like 'as<set>', 'as<deque>',
2025 * 'as<vector>'. 'as', here is the helper method which is the usual means of
2026 * constructing this operator.
2030 * set<string> uniqueNames = from(names) | as<set>();
2033 template <class, class> class Container,
2034 template <class> class Allocator>
2035 class CollectTemplate : public Operator<CollectTemplate<Container, Allocator>> {
2037 CollectTemplate() = default;
2042 class StorageType = typename std::decay<Value>::type,
2043 class Collection = Container<StorageType, Allocator<StorageType>>>
2044 Collection compose(const GenImpl<Value, Source>& source) const {
2045 static_assert(!Source::infinite,
2046 "Cannot convert infinite source to object with as.");
2047 Collection collection;
2048 source | [&](Value v) {
2049 collection.insert(collection.end(), std::forward<Value>(v));
2056 * UnwrapOr - For unwrapping folly::Optional values, or providing the given
2057 * fallback value. Usually used through the 'unwrapOr' helper like so:
2059 * auto best = from(scores) | max | unwrapOr(-1);
2061 * Note that the fallback value needn't match the value in the Optional it is
2062 * unwrapping. If mis-matched types are supported, the common type of the two is
2063 * returned by value. If the types match, a reference (T&& > T& > const T&) is
2069 explicit UnwrapOr(T&& value) : value_(std::move(value)) {}
2070 explicit UnwrapOr(const T& value) : value_(value) {}
2072 T& value() { return value_; }
2073 const T& value() const { return value_; }
2080 T&& operator|(Optional<T>&& opt, UnwrapOr<T>&& fallback) {
2081 if (T* p = opt.get_pointer()) {
2082 return std::move(*p);
2084 return std::move(fallback.value());
2088 T& operator|(Optional<T>& opt, UnwrapOr<T>& fallback) {
2089 if (T* p = opt.get_pointer()) {
2092 return fallback.value();
2096 const T& operator|(const Optional<T>& opt, const UnwrapOr<T>& fallback) {
2097 if (const T* p = opt.get_pointer()) {
2100 return fallback.value();
2103 // Mixed type unwrapping always returns values, moving where possible
2107 class R = typename std::enable_if<
2108 !std::is_same<T, U>::value,
2109 typename std::common_type<T, U>::type>::type>
2110 R operator|(Optional<T>&& opt, UnwrapOr<U>&& fallback) {
2111 if (T* p = opt.get_pointer()) {
2112 return std::move(*p);
2114 return std::move(fallback.value());
2120 class R = typename std::enable_if<
2121 !std::is_same<T, U>::value,
2122 typename std::common_type<T, U>::type>::type>
2123 R operator|(const Optional<T>& opt, UnwrapOr<U>&& fallback) {
2124 if (const T* p = opt.get_pointer()) {
2127 return std::move(fallback.value());
2133 class R = typename std::enable_if<
2134 !std::is_same<T, U>::value,
2135 typename std::common_type<T, U>::type>::type>
2136 R operator|(Optional<T>&& opt, const UnwrapOr<U>& fallback) {
2137 if (T* p = opt.get_pointer()) {
2138 return std::move(*p);
2140 return fallback.value();
2146 class R = typename std::enable_if<
2147 !std::is_same<T, U>::value,
2148 typename std::common_type<T, U>::type>::type>
2149 R operator|(const Optional<T>& opt, const UnwrapOr<U>& fallback) {
2150 if (const T* p = opt.get_pointer()) {
2153 return fallback.value();
2157 * Unwrap - For unwrapping folly::Optional values in a folly::gen style. Usually
2158 * used through the 'unwrap' instace like so:
2160 * auto best = from(scores) | max | unwrap; // may throw
2165 T&& operator|(Optional<T>&& opt, const Unwrap&) {
2166 return std::move(opt.value());
2170 T& operator|(Optional<T>& opt, const Unwrap&) {
2175 const T& operator|(const Optional<T>& opt, const Unwrap&) {
2182 * VirtualGen<T> - For wrapping template types in simple polymorphic wrapper.
2184 template <class Value>
2185 class VirtualGen : public GenImpl<Value, VirtualGen<Value>> {
2188 virtual ~WrapperBase() noexcept {}
2189 virtual bool apply(const std::function<bool(Value)>& handler) const = 0;
2190 virtual void foreach(const std::function<void(Value)>& body) const = 0;
2191 virtual std::unique_ptr<const WrapperBase> clone() const = 0;
2194 template <class Wrapped>
2195 class WrapperImpl : public WrapperBase {
2199 explicit WrapperImpl(Wrapped wrapped) : wrapped_(std::move(wrapped)) {}
2201 bool apply(const std::function<bool(Value)>& handler) const override {
2202 return wrapped_.apply(handler);
2205 void foreach(const std::function<void(Value)>& body) const override {
2206 wrapped_.foreach(body);
2209 std::unique_ptr<const WrapperBase> clone() const override {
2210 return std::unique_ptr<const WrapperBase>(new WrapperImpl(wrapped_));
2214 std::unique_ptr<const WrapperBase> wrapper_;
2217 template <class Self>
2218 /* implicit */ VirtualGen(Self source)
2219 : wrapper_(new WrapperImpl<Self>(std::move(source))) {}
2221 VirtualGen(VirtualGen&& source) noexcept
2222 : wrapper_(std::move(source.wrapper_)) {}
2224 VirtualGen(const VirtualGen& source) : wrapper_(source.wrapper_->clone()) {}
2226 VirtualGen& operator=(const VirtualGen& source) {
2227 wrapper_.reset(source.wrapper_->clone());
2231 VirtualGen& operator=(VirtualGen&& source) noexcept {
2232 wrapper_ = std::move(source.wrapper_);
2236 bool apply(const std::function<bool(Value)>& handler) const {
2237 return wrapper_->apply(handler);
2240 void foreach(const std::function<void(Value)>& body) const {
2241 wrapper_->foreach(body);
2246 * non-template operators, statically defined to avoid the need for anything but
2249 constexpr detail::Sum sum{};
2251 constexpr detail::Count count{};
2253 constexpr detail::First first{};
2255 constexpr detail::IsEmpty<true> isEmpty{};
2257 constexpr detail::IsEmpty<false> notEmpty{};
2259 constexpr detail::Min<Identity, Less> min{};
2261 constexpr detail::Min<Identity, Greater> max{};
2263 constexpr detail::Order<Identity> order{};
2265 constexpr detail::Distinct<Identity> distinct{};
2267 constexpr detail::Map<Move> move{};
2269 constexpr detail::Concat concat{};
2271 constexpr detail::RangeConcat rconcat{};
2273 constexpr detail::Cycle<true> cycle{};
2275 constexpr detail::Dereference dereference{};
2277 constexpr detail::Indirect indirect{};
2279 constexpr detail::Unwrap unwrap{};
2281 template <class Number>
2282 inline detail::Take take(Number count) {
2284 throw std::invalid_argument("Negative value passed to take()");
2286 return detail::Take(static_cast<size_t>(count));
2289 inline detail::Stride stride(size_t s) { return detail::Stride(s); }
2291 template <class Random = std::default_random_engine>
2292 inline detail::Sample<Random> sample(size_t count, Random rng = Random()) {
2293 return detail::Sample<Random>(count, std::move(rng));
2296 inline detail::Skip skip(size_t count) { return detail::Skip(count); }
2298 inline detail::Batch batch(size_t batchSize) {
2299 return detail::Batch(batchSize);