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.
18 #define FOLLY_GEN_BASE_H_
24 #include <type_traits>
25 #include <unordered_map>
26 #include <unordered_set>
30 #include <folly/Conv.h>
31 #include <folly/Optional.h>
32 #include <folly/Range.h>
33 #include <folly/Utility.h>
34 #include <folly/gen/Core.h>
37 * Generator-based Sequence Comprehensions in C++, akin to C#'s LINQ
38 * @author Tom Jackson <tjackson@fb.com>
40 * This library makes it possible to write declarative comprehensions for
41 * processing sequences of values efficiently in C++. The operators should be
42 * familiar to those with experience in functional programming, and the
43 * performance will be virtually identical to the equivalent, boilerplate C++
46 * Generator objects may be created from either an stl-like container (anything
47 * supporting begin() and end()), from sequences of values, or from another
48 * generator (see below). To create a generator that pulls values from a vector,
49 * for example, one could write:
51 * vector<string> names { "Jack", "Jill", "Sara", "Tom" };
52 * auto gen = from(names);
54 * Generators are composed by building new generators out of old ones through
55 * the use of operators. These are reminicent of shell pipelines, and afford
56 * similar composition. Lambda functions are used liberally to describe how to
57 * handle individual values:
60 * | mapped([](const fbstring& name) { return name.size(); });
62 * Generators are lazy; they don't actually perform any work until they need to.
63 * As an example, the 'lengths' generator (above) won't actually invoke the
64 * provided lambda until values are needed:
66 * auto lengthVector = lengths | as<std::vector>();
67 * auto totalLength = lengths | sum;
69 * 'auto' is useful in here because the actual types of the generators objects
70 * are usually complicated and implementation-sensitive.
72 * If a simpler type is desired (for returning, as an example), VirtualGen<T>
73 * may be used to wrap the generator in a polymorphic wrapper:
75 * VirtualGen<float> powersOfE() {
76 * return seq(1) | mapped(&expf);
79 * To learn more about this library, including the use of infinite generators,
80 * see the examples in the comments, or the docs (coming soon).
83 namespace folly { namespace gen {
89 auto operator()(const First& first, const Second& second) const ->
90 decltype(first < second) {
91 return first < second;
99 auto operator()(const First& first, const Second& second) const ->
100 decltype(first > second) {
101 return first > second;
108 template<class Value>
109 auto operator()(Value&& value) const ->
110 decltype(std::get<n>(std::forward<Value>(value))) {
111 return std::get<n>(std::forward<Value>(value));
115 template<class Class,
117 class MemberFunction {
119 typedef Result (Class::*MemberPtr)();
123 explicit MemberFunction(MemberPtr member)
127 Result operator()(Class&& x) const {
128 return (x.*member_)();
131 Result operator()(Class& x) const {
132 return (x.*member_)();
135 Result operator()(Class* x) const {
136 return (x->*member_)();
140 template<class Class,
142 class ConstMemberFunction{
144 typedef Result (Class::*MemberPtr)() const;
148 explicit ConstMemberFunction(MemberPtr member)
152 Result operator()(const Class& x) const {
153 return (x.*member_)();
156 Result operator()(const Class* x) const {
157 return (x->*member_)();
161 template<class Class,
165 typedef FieldType (Class::*FieldPtr);
169 explicit Field(FieldPtr field)
173 const FieldType& operator()(const Class& x) const {
177 const FieldType& operator()(const Class* x) const {
181 FieldType& operator()(Class& x) const {
185 FieldType& operator()(Class* x) const {
189 FieldType&& operator()(Class&& x) const {
190 return std::move(x.*field_);
196 template<class Value>
197 auto operator()(Value&& value) const ->
198 decltype(std::move(std::forward<Value>(value))) {
199 return std::move(std::forward<Value>(value));
204 * Class and helper function for negating a boolean Predicate
206 template <class Predicate>
213 explicit Negate(Predicate pred)
214 : pred_(std::move(pred))
218 bool operator()(Arg&& arg) const {
219 return !pred_(std::forward<Arg>(arg));
222 template <class Predicate>
223 Negate<Predicate> negate(Predicate pred) {
224 return Negate<Predicate>(std::move(pred));
227 template <class Dest>
230 template <class Value>
231 Dest operator()(Value&& value) const {
232 return Dest(std::forward<Value>(value));
236 template <class Dest>
239 template <class Value>
240 Dest operator()(Value&& value) const {
241 return ::folly::to<Dest>(std::forward<Value>(value));
245 // Specialization to allow String->StringPiece conversion
247 class To<StringPiece> {
249 StringPiece operator()(StringPiece src) const {
254 template<class Key, class Value>
265 template<class Container>
266 struct ValueTypeOfRange {
268 using RefType = decltype(*std::begin(std::declval<Container&>()));
269 using StorageType = typename std::decay<RefType>::type;
276 template<class Container,
277 class Value = typename ValueTypeOfRange<Container>::RefType>
278 class ReferencedSource;
280 template<class Value,
281 class Container = std::vector<typename std::decay<Value>::type>>
284 template<class Value, class SequenceImpl>
287 template <class Value>
290 template <class Value, class Distance>
291 class RangeWithStepImpl;
293 template <class Value>
296 template <class Value, class Distance>
297 class SeqWithStepImpl;
299 template <class Value>
302 template<class Value, class Source>
305 template<class Value>
308 template<class Value>
309 class SingleReference;
311 template<class Value>
317 template<class Predicate>
320 template<class Predicate>
323 template<class Predicate>
335 template<class Selector, class Comparer = Less>
338 template<class Selector>
341 template<class Selector>
344 template<class Operators>
347 template<class Expected>
354 template <bool forever>
372 template <bool result>
375 template<class Reducer>
380 template<class Selector,
384 template<class Container>
387 template<template<class, class> class Collection = std::vector,
388 template<class> class Allocator = std::allocator>
389 class CollectTemplate;
391 template<class Collection>
394 template<class Value>
395 struct GeneratorBuilder;
397 template<class Needle>
400 template<class Exception,
412 * Polymorphic wrapper
414 template<class Value>
420 template<class Container,
421 class From = detail::ReferencedSource<const Container>>
422 From fromConst(const Container& source) {
423 return From(&source);
426 template<class Container,
427 class From = detail::ReferencedSource<Container>>
428 From from(Container& source) {
429 return From(&source);
432 template<class Container,
434 typename detail::ValueTypeOfRange<Container>::StorageType,
435 class CopyOf = detail::CopiedSource<Value>>
436 CopyOf fromCopy(Container&& source) {
437 return CopyOf(std::forward<Container>(source));
440 template<class Value,
441 class From = detail::CopiedSource<Value>>
442 From from(std::initializer_list<Value> source) {
446 template<class Container,
447 class From = detail::CopiedSource<typename Container::value_type,
449 From from(Container&& source) {
450 return From(std::move(source));
453 template<class Value, class Impl = detail::RangeImpl<Value>,
454 class Gen = detail::Sequence<Value, Impl>>
455 Gen range(Value begin, Value end) {
456 return Gen{std::move(begin), Impl{std::move(end)}};
459 template<class Value, class Distance,
460 class Impl = detail::RangeWithStepImpl<Value, Distance>,
461 class Gen = detail::Sequence<Value, Impl>>
462 Gen range(Value begin, Value end, Distance step) {
463 return Gen{std::move(begin), Impl{std::move(end), std::move(step)}};
466 template<class Value, class Impl = detail::SeqImpl<Value>,
467 class Gen = detail::Sequence<Value, Impl>>
468 Gen seq(Value first, Value last) {
469 return Gen{std::move(first), Impl{std::move(last)}};
472 template<class Value, class Distance,
473 class Impl = detail::SeqWithStepImpl<Value, Distance>,
474 class Gen = detail::Sequence<Value, Impl>>
475 Gen seq(Value first, Value last, Distance step) {
476 return Gen{std::move(first), Impl{std::move(last), std::move(step)}};
479 template<class Value, class Impl = detail::InfiniteImpl<Value>,
480 class Gen = detail::Sequence<Value, Impl>>
481 Gen seq(Value first) {
482 return Gen{std::move(first), Impl{}};
485 template<class Value,
487 class Yield = detail::Yield<Value, Source>>
488 Yield generator(Source&& source) {
489 return Yield(std::forward<Source>(source));
493 * Create inline generator, used like:
495 * auto gen = GENERATOR(int) { yield(1); yield(2); };
497 #define GENERATOR(TYPE) \
498 ::folly::gen::detail::GeneratorBuilder<TYPE>() + \
499 [=](const std::function<void(TYPE)>& yield)
502 * empty() - for producing empty sequences.
504 template <class Value>
505 detail::Empty<Value> empty() {
511 class Just = typename std::conditional<
512 std::is_reference<Value>::value,
513 detail::SingleReference<typename std::remove_reference<Value>::type>,
514 detail::SingleCopy<Value>>::type>
515 Just just(Value&& value) {
516 return Just(std::forward<Value>(value));
522 template<class Predicate,
523 class Map = detail::Map<Predicate>>
524 Map mapped(Predicate pred = Predicate()) {
525 return Map(std::move(pred));
528 template<class Predicate,
529 class Map = detail::Map<Predicate>>
530 Map map(Predicate pred = Predicate()) {
531 return Map(std::move(pred));
535 * mapOp - Given a generator of generators, maps the application of the given
536 * operator on to each inner gen. Especially useful in aggregating nested data
539 * chunked(samples, 256)
540 * | mapOp(filter(sampleTest) | count)
543 template<class Operator,
544 class Map = detail::Map<detail::Composer<Operator>>>
545 Map mapOp(Operator op) {
546 return Map(detail::Composer<Operator>(std::move(op)));
550 * member(...) - For extracting a member from each value.
552 * vector<string> strings = ...;
553 * auto sizes = from(strings) | member(&string::size);
555 * If a member is const overridden (like 'front()'), pass template parameter
556 * 'Const' to select the const version, or 'Mutable' to select the non-const
559 * auto heads = from(strings) | member<Const>(&string::front);
567 * These exist because MSVC has problems with expression SFINAE in templates
568 * assignment and comparisons don't work properly without being pulled out
569 * of the template declaration
571 template <MemberType Constness> struct ExprIsConst {
573 value = Constness == Const
577 template <MemberType Constness> struct ExprIsMutable {
579 value = Constness == Mutable
583 template<MemberType Constness = Const,
586 class Mem = ConstMemberFunction<Class, Return>,
587 class Map = detail::Map<Mem>>
588 typename std::enable_if<ExprIsConst<Constness>::value, Map>::type
589 member(Return (Class::*member)() const) {
590 return Map(Mem(member));
593 template<MemberType Constness = Mutable,
596 class Mem = MemberFunction<Class, Return>,
597 class Map = detail::Map<Mem>>
598 typename std::enable_if<ExprIsMutable<Constness>::value, Map>::type
599 member(Return (Class::*member)()) {
600 return Map(Mem(member));
604 * field(...) - For extracting a field from each value.
606 * vector<Item> items = ...;
607 * auto names = from(items) | field(&Item::name);
609 * Note that if the values of the generator are rvalues, any non-reference
610 * fields will be rvalues as well. As an example, the code below does not copy
611 * any strings, only moves them:
613 * auto namesVector = from(items)
615 * | field(&Item::name)
618 template<class Class,
620 class Field = Field<Class, FieldType>,
621 class Map = detail::Map<Field>>
622 Map field(FieldType Class::*field) {
623 return Map(Field(field));
626 template <class Predicate = Identity,
627 class Filter = detail::Filter<Predicate>>
628 Filter filter(Predicate pred = Predicate()) {
629 return Filter(std::move(pred));
632 template<class Predicate,
633 class Until = detail::Until<Predicate>>
634 Until until(Predicate pred = Predicate()) {
635 return Until(std::move(pred));
638 template<class Selector = Identity,
639 class Comparer = Less,
640 class Order = detail::Order<Selector, Comparer>>
641 Order orderBy(Selector selector = Selector(),
642 Comparer comparer = Comparer()) {
643 return Order(std::move(selector),
644 std::move(comparer));
647 template<class Selector = Identity,
648 class Order = detail::Order<Selector, Greater>>
649 Order orderByDescending(Selector selector = Selector()) {
650 return Order(std::move(selector));
653 template <class Selector = Identity,
654 class GroupBy = detail::GroupBy<Selector>>
655 GroupBy groupBy(Selector selector = Selector()) {
656 return GroupBy(std::move(selector));
659 template<class Selector = Identity,
660 class Distinct = detail::Distinct<Selector>>
661 Distinct distinctBy(Selector selector = Selector()) {
662 return Distinct(std::move(selector));
666 class Get = detail::Map<Get<n>>>
671 // construct Dest from each value
672 template <class Dest,
673 class Cast = detail::Map<Cast<Dest>>>
678 // call folly::to on each value
679 template <class Dest,
680 class To = detail::Map<To<Dest>>>
685 template<class Value>
686 detail::TypeAssertion<Value> assert_type() {
695 * any() - For determining if any value in a sequence satisfies a predicate.
697 * The following is an example for checking if any computer is broken:
699 * bool schrepIsMad = from(computers) | any(isBroken);
701 * (because everyone knows Schrep hates broken computers).
703 * Note that if no predicate is provided, 'any()' checks if any of the values
704 * are true when cased to bool. To check if any of the scores are nonZero:
706 * bool somebodyScored = from(scores) | any();
708 * Note: Passing an empty sequence through 'any()' will always return false. In
709 * fact, 'any()' is equivilent to the composition of 'filter()' and 'notEmpty'.
711 * from(source) | any(pred) == from(source) | filter(pred) | notEmpty
714 template <class Predicate = Identity,
715 class Filter = detail::Filter<Predicate>,
716 class NotEmpty = detail::IsEmpty<false>,
717 class Composed = detail::Composed<Filter, NotEmpty>>
718 Composed any(Predicate pred = Predicate()) {
719 return Composed(Filter(std::move(pred)), NotEmpty());
723 * all() - For determining whether all values in a sequence satisfy a predicate.
725 * The following is an example for checking if all members of a team are cool:
727 * bool isAwesomeTeam = from(team) | all(isCool);
729 * Note that if no predicate is provided, 'all()'' checks if all of the values
730 * are true when cased to bool.
731 * The following makes sure none of 'pointers' are nullptr:
733 * bool allNonNull = from(pointers) | all();
735 * Note: Passing an empty sequence through 'all()' will always return true. In
736 * fact, 'all()' is equivilent to the composition of 'filter()' with the
737 * reversed predicate and 'isEmpty'.
739 * from(source) | all(pred) == from(source) | filter(negate(pred)) | isEmpty
742 template <class Predicate = Identity,
743 class Filter = detail::Filter<Negate<Predicate>>,
744 class IsEmpty = detail::IsEmpty<true>,
745 class Composed = detail::Composed<Filter, IsEmpty>>
746 Composed all(Predicate pred = Predicate()) {
747 return Composed(Filter(std::move(negate(pred))), IsEmpty());
752 class FoldLeft = detail::FoldLeft<Seed, Fold>>
753 FoldLeft foldl(Seed seed = Seed(),
754 Fold fold = Fold()) {
755 return FoldLeft(std::move(seed),
759 template<class Reducer,
760 class Reduce = detail::Reduce<Reducer>>
761 Reduce reduce(Reducer reducer = Reducer()) {
762 return Reduce(std::move(reducer));
765 template<class Selector = Identity,
766 class Min = detail::Min<Selector, Less>>
767 Min minBy(Selector selector = Selector()) {
768 return Min(std::move(selector));
771 template<class Selector,
772 class MaxBy = detail::Min<Selector, Greater>>
773 MaxBy maxBy(Selector selector = Selector()) {
774 return MaxBy(std::move(selector));
777 template<class Collection,
778 class Collect = detail::Collect<Collection>>
783 template<template<class, class> class Container = std::vector,
784 template<class> class Allocator = std::allocator,
785 class Collect = detail::CollectTemplate<Container, Allocator>>
790 template<class Collection,
791 class Append = detail::Append<Collection>>
792 Append appendTo(Collection& collection) {
793 return Append(&collection);
796 template<class Needle,
797 class Contains = detail::Contains<typename std::decay<Needle>::type>>
798 Contains contains(Needle&& needle) {
799 return Contains(std::forward<Needle>(needle));
802 template<class Exception,
807 typename std::decay<ErrorHandler>::type>>
808 GuardImpl guard(ErrorHandler&& handler) {
809 return GuardImpl(std::forward<ErrorHandler>(handler));
812 template<class Fallback,
813 class UnwrapOr = detail::UnwrapOr<typename std::decay<Fallback>::type>>
814 UnwrapOr unwrapOr(Fallback&& fallback) {
815 return UnwrapOr(std::forward<Fallback>(fallback));
820 #include <folly/gen/Base-inl.h>