Fix copyright lines
[folly.git] / folly / gen / Base.h
index 12d917edac6a3bed58f9907f2f056fdc4fd39d11..250b862e9af714e952bb8f361156bc249795fa03 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2014-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-#ifndef FOLLY_GEN_BASE_H
-#define FOLLY_GEN_BASE_H
+#pragma once
+#define FOLLY_GEN_BASE_H_
 
+#include <algorithm>
 #include <functional>
 #include <memory>
+#include <random>
 #include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
 #include <utility>
-#include <algorithm>
-#include <random>
 #include <vector>
-#include <unordered_set>
 
-#include <folly/Range.h>
-#include <folly/Optional.h>
 #include <folly/Conv.h>
+#include <folly/Optional.h>
+#include <folly/Range.h>
+#include <folly/Utility.h>
 #include <folly/gen/Core.h>
 
 /**
  *
  * To learn more about this library, including the use of infinite generators,
  * see the examples in the comments, or the docs (coming soon).
-*/
+ */
 
-namespace folly { namespace gen {
-
-class EmptySequence : public std::exception {
-public:
-  virtual const char* what() const noexcept {
-    return "This operation cannot be called on an empty sequence";
-  }
-};
+namespace folly {
+namespace gen {
 
 class Less {
-public:
-  template<class First,
-           class Second>
+ public:
+  template <class First, class Second>
   auto operator()(const First& first, const Second& second) const ->
   decltype(first < second) {
     return first < second;
@@ -98,27 +93,25 @@ public:
 };
 
 class Greater {
-public:
-  template<class First,
-           class Second>
+ public:
+  template <class First, class Second>
   auto operator()(const First& first, const Second& second) const ->
   decltype(first > second) {
     return first > second;
   }
 };
 
-template<int n>
+template <int n>
 class Get {
-public:
-  template<class Value>
+ public:
+  template <class Value>
   auto operator()(Value&& value) const ->
   decltype(std::get<n>(std::forward<Value>(value))) {
     return std::get<n>(std::forward<Value>(value));
   }
 };
 
-template<class Class,
-         class Result>
+template <class Class, class Result>
 class MemberFunction {
  public:
   typedef Result (Class::*MemberPtr)();
@@ -142,8 +135,7 @@ class MemberFunction {
   }
 };
 
-template<class Class,
-         class Result>
+template <class Class, class Result>
 class ConstMemberFunction{
  public:
   typedef Result (Class::*MemberPtr)() const;
@@ -163,8 +155,7 @@ class ConstMemberFunction{
   }
 };
 
-template<class Class,
-         class FieldType>
+template <class Class, class FieldType>
 class Field {
  public:
   typedef FieldType (Class::*FieldPtr);
@@ -197,22 +188,37 @@ class Field {
 };
 
 class Move {
-public:
-  template<class Value>
+ public:
+  template <class Value>
   auto operator()(Value&& value) const ->
   decltype(std::move(std::forward<Value>(value))) {
     return std::move(std::forward<Value>(value));
   }
 };
 
-class Identity {
-public:
-  template<class Value>
-  auto operator()(Value&& value) const ->
-  decltype(std::forward<Value>(value)) {
-    return std::forward<Value>(value);
+/**
+ * Class and helper function for negating a boolean Predicate
+ */
+template <class Predicate>
+class Negate {
+  Predicate pred_;
+
+ public:
+  Negate() = default;
+
+  explicit Negate(Predicate pred)
+    : pred_(std::move(pred))
+  {}
+
+  template <class Arg>
+  bool operator()(Arg&& arg) const {
+    return !pred_(std::forward<Arg>(arg));
   }
 };
+template <class Predicate>
+Negate<Predicate> negate(Predicate pred) {
+  return Negate<Predicate>(std::move(pred));
+}
 
 template <class Dest>
 class Cast {
@@ -241,38 +247,39 @@ class To<StringPiece> {
   }
 };
 
+template <class Key, class Value>
+class Group;
+
 namespace detail {
 
-template<class Self>
+template <class Self>
 struct FBounded;
 
 /*
  * Type Traits
  */
-template<class Container>
+template <class Container>
 struct ValueTypeOfRange {
- private:
-  static Container container_;
  public:
-  typedef decltype(*std::begin(container_))
-    RefType;
-  typedef typename std::decay<decltype(*std::begin(container_))>::type
-    StorageType;
+  using RefType = decltype(*std::begin(std::declval<Container&>()));
+  using StorageType = typename std::decay<RefType>::type;
 };
 
 
 /*
  * Sources
  */
-template<class Container,
-         class Value = typename ValueTypeOfRange<Container>::RefType>
+template <
+    class Container,
+    class Value = typename ValueTypeOfRange<Container>::RefType>
 class ReferencedSource;
 
-template<class Value,
-         class Container = std::vector<typename std::decay<Value>::type>>
+template <
+    class Value,
+    class Container = std::vector<typename std::decay<Value>::type>>
 class CopiedSource;
 
-template<class Value, class SequenceImpl>
+template <class Value, class SequenceImpl>
 class Sequence;
 
 template <class Value>
@@ -290,56 +297,68 @@ class SeqWithStepImpl;
 template <class Value>
 class InfiniteImpl;
 
-template<class Value, class Source>
+template <class Value, class Source>
 class Yield;
 
-template<class Value>
+template <class Value>
 class Empty;
 
-template<class Value>
-class Just;
+template <class Value>
+class SingleReference;
+
+template <class Value>
+class SingleCopy;
 
 /*
  * Operators
  */
-template<class Predicate>
+template <class Predicate>
 class Map;
 
-template<class Predicate>
+template <class Predicate>
 class Filter;
 
-template<class Predicate>
+template <class Predicate>
 class Until;
 
 class Take;
 
 class Stride;
 
-template<class Rand>
+template <class Rand>
 class Sample;
 
 class Skip;
 
-template<class Selector, class Comparer = Less>
+template <class Visitor>
+class Visit;
+
+template <class Selector, class Comparer = Less>
 class Order;
 
-template<class Selector>
+template <class Selector>
+class GroupBy;
+
+template <class Selector>
 class Distinct;
 
-template<class Operators>
+template <class Operators>
 class Composer;
 
-template<class Expected>
+template <class Expected>
 class TypeAssertion;
 
 class Concat;
 
 class RangeConcat;
 
+template <bool forever>
 class Cycle;
 
 class Batch;
 
+class Window;
+
 class Dereference;
 
 class Indirect;
@@ -347,125 +366,134 @@ class Indirect;
 /*
  * Sinks
  */
-template<class Seed,
-         class Fold>
+template <class Seed, class Fold>
 class FoldLeft;
 
 class First;
 
-class Any;
-
-template<class Predicate>
-class All;
+template <bool result>
+class IsEmpty;
 
-template<class Reducer>
+template <class Reducer>
 class Reduce;
 
 class Sum;
 
-template<class Selector,
-         class Comparer>
+template <class Selector, class Comparer>
 class Min;
 
-template<class Container>
+template <class Container>
 class Collect;
 
-template<template<class, class> class Collection = std::vector,
-         template<class> class Allocator = std::allocator>
+template <
+    template <class, class> class Collection = std::vector,
+    template <class> class Allocator = std::allocator>
 class CollectTemplate;
 
-template<class Collection>
+template <class Collection>
 class Append;
 
-template<class Value>
+template <class Value>
 struct GeneratorBuilder;
 
-template<class Needle>
+template <class Needle>
 class Contains;
 
-template<class Exception,
-         class ErrorHandler>
+template <class Exception, class ErrorHandler>
 class GuardImpl;
 
-}
+template <class T>
+class UnwrapOr;
+
+class Unwrap;
+
+} // namespace detail
 
 /**
  * Polymorphic wrapper
  **/
-template<class Value>
+template <class Value>
 class VirtualGen;
 
 /*
  * Source Factories
  */
-template<class Container,
-         class From = detail::ReferencedSource<const Container>>
+template <
+    class Container,
+    class From = detail::ReferencedSource<const Container>>
 From fromConst(const Container& source) {
   return From(&source);
 }
 
-template<class Container,
-         class From = detail::ReferencedSource<Container>>
+template <class Container, class From = detail::ReferencedSource<Container>>
 From from(Container& source) {
   return From(&source);
 }
 
-template<class Container,
-         class Value =
-           typename detail::ValueTypeOfRange<Container>::StorageType,
-         class CopyOf = detail::CopiedSource<Value>>
+template <
+    class Container,
+    class Value = typename detail::ValueTypeOfRange<Container>::StorageType,
+    class CopyOf = detail::CopiedSource<Value>>
 CopyOf fromCopy(Container&& source) {
   return CopyOf(std::forward<Container>(source));
 }
 
-template<class Value,
-         class From = detail::CopiedSource<Value>>
+template <class Value, class From = detail::CopiedSource<Value>>
 From from(std::initializer_list<Value> source) {
   return From(source);
 }
 
-template<class Container,
-         class From = detail::CopiedSource<typename Container::value_type,
-                                           Container>>
+template <
+    class Container,
+    class From =
+        detail::CopiedSource<typename Container::value_type, Container>>
 From from(Container&& source) {
   return From(std::move(source));
 }
 
-template<class Value, class Impl = detail::RangeImpl<Value>,
-         class Gen = detail::Sequence<Value, Impl>>
+template <
+    class Value,
+    class Impl = detail::RangeImpl<Value>,
+    class Gen = detail::Sequence<Value, Impl>>
 Gen range(Value begin, Value end) {
   return Gen{std::move(begin), Impl{std::move(end)}};
 }
 
-template<class Value, class Distance,
-         class Impl = detail::RangeWithStepImpl<Value, Distance>,
-         class Gen = detail::Sequence<Value, Impl>>
+template <
+    class Value,
+    class Distance,
+    class Impl = detail::RangeWithStepImpl<Value, Distance>,
+    class Gen = detail::Sequence<Value, Impl>>
 Gen range(Value begin, Value end, Distance step) {
   return Gen{std::move(begin), Impl{std::move(end), std::move(step)}};
 }
 
-template<class Value, class Impl = detail::SeqImpl<Value>,
-         class Gen = detail::Sequence<Value, Impl>>
+template <
+    class Value,
+    class Impl = detail::SeqImpl<Value>,
+    class Gen = detail::Sequence<Value, Impl>>
 Gen seq(Value first, Value last) {
   return Gen{std::move(first), Impl{std::move(last)}};
 }
 
-template<class Value, class Distance,
-         class Impl = detail::SeqWithStepImpl<Value, Distance>,
-         class Gen = detail::Sequence<Value, Impl>>
+template <
+    class Value,
+    class Distance,
+    class Impl = detail::SeqWithStepImpl<Value, Distance>,
+    class Gen = detail::Sequence<Value, Impl>>
 Gen seq(Value first, Value last, Distance step) {
   return Gen{std::move(first), Impl{std::move(last), std::move(step)}};
 }
 
-template<class Value, class Impl = detail::InfiniteImpl<Value>,
-         class Gen = detail::Sequence<Value, Impl>>
+template <
+    class Value,
+    class Impl = detail::InfiniteImpl<Value>,
+    class Gen = detail::Sequence<Value, Impl>>
 Gen seq(Value first) {
   return Gen{std::move(first), Impl{}};
 }
 
-template<class Value,
-         class Source,
-         class Yield = detail::Yield<Value, Source>>
+template <class Value, class Source, class Yield = detail::Yield<Value, Source>>
 Yield generator(Source&& source) {
   return Yield(std::forward<Source>(source));
 }
@@ -475,34 +503,36 @@ Yield generator(Source&& source) {
  *
  *  auto gen = GENERATOR(int) { yield(1); yield(2); };
  */
-#define GENERATOR(TYPE)                            \
-  ::folly::gen::detail::GeneratorBuilder<TYPE>() + \
-   [=](const std::function<void(TYPE)>& yield)
+#define GENERATOR(TYPE) \
+  ::folly::gen::detail::GeneratorBuilder<TYPE>() + [=](auto&& yield)
 
 /*
  * empty() - for producing empty sequences.
  */
-template<class Value>
+template <class Value>
 detail::Empty<Value> empty() {
   return {};
 }
 
-template<class Value>
-detail::Just<Value> just(Value value) {
-  return detail::Just<Value>(std::move(value));
+template <
+    class Value,
+    class Just = typename std::conditional<
+        std::is_reference<Value>::value,
+        detail::SingleReference<typename std::remove_reference<Value>::type>,
+        detail::SingleCopy<Value>>::type>
+Just just(Value&& value) {
+  return Just(std::forward<Value>(value));
 }
 
 /*
  * Operator Factories
  */
-template<class Predicate,
-         class Map = detail::Map<Predicate>>
+template <class Predicate, class Map = detail::Map<Predicate>>
 Map mapped(Predicate pred = Predicate()) {
   return Map(std::move(pred));
 }
 
-template<class Predicate,
-         class Map = detail::Map<Predicate>>
+template <class Predicate, class Map = detail::Map<Predicate>>
 Map map(Predicate pred = Predicate()) {
   return Map(std::move(pred));
 }
@@ -516,8 +546,7 @@ Map map(Predicate pred = Predicate()) {
  *     | mapOp(filter(sampleTest) | count)
  *     | sum;
  */
-template<class Operator,
-         class Map = detail::Map<detail::Composer<Operator>>>
+template <class Operator, class Map = detail::Map<detail::Composer<Operator>>>
 Map mapOp(Operator op) {
   return Map(detail::Composer<Operator>(std::move(op)));
 }
@@ -544,33 +573,37 @@ enum MemberType {
  * assignment and comparisons don't work properly without being pulled out
  * of the template declaration
  */
-template <MemberType Constness> struct ExprIsConst {
+template <MemberType Constness>
+struct ExprIsConst {
   enum {
     value = Constness == Const
   };
 };
 
-template <MemberType Constness> struct ExprIsMutable {
+template <MemberType Constness>
+struct ExprIsMutable {
   enum {
     value = Constness == Mutable
   };
 };
 
-template<MemberType Constness = Const,
-         class Class,
-         class Return,
-         class Mem = ConstMemberFunction<Class, Return>,
-         class Map = detail::Map<Mem>>
+template <
+    MemberType Constness = Const,
+    class Class,
+    class Return,
+    class Mem = ConstMemberFunction<Class, Return>,
+    class Map = detail::Map<Mem>>
 typename std::enable_if<ExprIsConst<Constness>::value, Map>::type
 member(Return (Class::*member)() const) {
   return Map(Mem(member));
 }
 
-template<MemberType Constness = Mutable,
-         class Class,
-         class Return,
-         class Mem = MemberFunction<Class, Return>,
-         class Map = detail::Map<Mem>>
+template <
+    MemberType Constness = Mutable,
+    class Class,
+    class Return,
+    class Mem = MemberFunction<Class, Return>,
+    class Map = detail::Map<Mem>>
 typename std::enable_if<ExprIsMutable<Constness>::value, Map>::type
 member(Return (Class::*member)()) {
   return Map(Mem(member));
@@ -591,74 +624,77 @@ member(Return (Class::*member)()) {
  *                   | field(&Item::name)
  *                   | as<vector>();
  */
-template<class Class,
-         class FieldType,
-         class Field = Field<Class, FieldType>,
-         class Map = detail::Map<Field>>
+template <
+    class Class,
+    class FieldType,
+    class Field = Field<Class, FieldType>,
+    class Map = detail::Map<Field>>
 Map field(FieldType Class::*field) {
   return Map(Field(field));
 }
 
-template<class Predicate,
-         class Filter = detail::Filter<Predicate>>
+template <class Predicate = Identity, class Filter = detail::Filter<Predicate>>
 Filter filter(Predicate pred = Predicate()) {
   return Filter(std::move(pred));
 }
 
-template<class Predicate,
-         class All = detail::All<Predicate>>
-All all(Predicate pred = Predicate()) {
-  return All(std::move(pred));
+template <class Visitor = Ignore, class Visit = detail::Visit<Visitor>>
+Visit visit(Visitor visitor = Visitor()) {
+  return Visit(std::move(visitor));
 }
 
-template<class Predicate,
-         class Until = detail::Until<Predicate>>
+template <class Predicate, class Until = detail::Until<Predicate>>
 Until until(Predicate pred = Predicate()) {
   return Until(std::move(pred));
 }
 
-template<class Selector,
-         class Comparer = Less,
-         class Order = detail::Order<Selector, Comparer>>
-Order orderBy(Selector selector = Identity(),
+template <
+    class Selector = Identity,
+    class Comparer = Less,
+    class Order = detail::Order<Selector, Comparer>>
+Order orderBy(Selector selector = Selector(),
               Comparer comparer = Comparer()) {
   return Order(std::move(selector),
                std::move(comparer));
 }
 
-template<class Selector,
-         class Order = detail::Order<Selector, Greater>>
-Order orderByDescending(Selector selector = Identity()) {
+template <
+    class Selector = Identity,
+    class Order = detail::Order<Selector, Greater>>
+Order orderByDescending(Selector selector = Selector()) {
   return Order(std::move(selector));
 }
 
-template<class Selector,
-         class Distinct = detail::Distinct<Selector>>
-Distinct distinctBy(Selector selector = Identity()) {
+template <class Selector = Identity, class GroupBy = detail::GroupBy<Selector>>
+GroupBy groupBy(Selector selector = Selector()) {
+  return GroupBy(std::move(selector));
+}
+
+template <
+    class Selector = Identity,
+    class Distinct = detail::Distinct<Selector>>
+Distinct distinctBy(Selector selector = Selector()) {
   return Distinct(std::move(selector));
 }
 
-template<int n,
-         class Get = detail::Map<Get<n>>>
+template <int n, class Get = detail::Map<Get<n>>>
 Get get() {
   return Get();
 }
 
 // construct Dest from each value
-template <class Dest,
-          class Cast = detail::Map<Cast<Dest>>>
+template <class Dest, class Cast = detail::Map<Cast<Dest>>>
 Cast eachAs() {
   return Cast();
 }
 
 // call folly::to on each value
-template <class Dest,
-          class To = detail::Map<To<Dest>>>
+template <class Dest, class To = detail::Map<To<Dest>>>
 To eachTo() {
   return To();
 }
 
-template<class Value>
+template <class Value>
 detail::TypeAssertion<Value> assert_type() {
   return {};
 }
@@ -666,70 +702,128 @@ detail::TypeAssertion<Value> assert_type() {
 /*
  * Sink Factories
  */
-template<class Seed,
-         class Fold,
-         class FoldLeft = detail::FoldLeft<Seed, Fold>>
+
+/**
+ * any() - For determining if any value in a sequence satisfies a predicate.
+ *
+ * The following is an example for checking if any computer is broken:
+ *
+ *   bool schrepIsMad = from(computers) | any(isBroken);
+ *
+ * (because everyone knows Schrep hates broken computers).
+ *
+ * Note that if no predicate is provided, 'any()' checks if any of the values
+ * are true when cased to bool. To check if any of the scores are nonZero:
+ *
+ *   bool somebodyScored = from(scores) | any();
+ *
+ * Note: Passing an empty sequence through 'any()' will always return false. In
+ * fact, 'any()' is equivilent to the composition of 'filter()' and 'notEmpty'.
+ *
+ *   from(source) | any(pred) == from(source) | filter(pred) | notEmpty
+ */
+
+template <
+    class Predicate = Identity,
+    class Filter = detail::Filter<Predicate>,
+    class NotEmpty = detail::IsEmpty<false>,
+    class Composed = detail::Composed<Filter, NotEmpty>>
+Composed any(Predicate pred = Predicate()) {
+  return Composed(Filter(std::move(pred)), NotEmpty());
+}
+
+/**
+ * all() - For determining whether all values in a sequence satisfy a predicate.
+ *
+ * The following is an example for checking if all members of a team are cool:
+ *
+ *   bool isAwesomeTeam = from(team) | all(isCool);
+ *
+ * Note that if no predicate is provided, 'all()'' checks if all of the values
+ * are true when cased to bool.
+ * The following makes sure none of 'pointers' are nullptr:
+ *
+ *   bool allNonNull = from(pointers) | all();
+ *
+ * Note: Passing an empty sequence through 'all()' will always return true. In
+ * fact, 'all()' is equivilent to the composition of 'filter()' with the
+ * reversed predicate and 'isEmpty'.
+ *
+ *   from(source) | all(pred) == from(source) | filter(negate(pred)) | isEmpty
+ */
+template <
+    class Predicate = Identity,
+    class Filter = detail::Filter<Negate<Predicate>>,
+    class IsEmpty = detail::IsEmpty<true>,
+    class Composed = detail::Composed<Filter, IsEmpty>>
+Composed all(Predicate pred = Predicate()) {
+  return Composed(Filter(std::move(negate(pred))), IsEmpty());
+}
+
+template <class Seed, class Fold, class FoldLeft = detail::FoldLeft<Seed, Fold>>
 FoldLeft foldl(Seed seed = Seed(),
                Fold fold = Fold()) {
   return FoldLeft(std::move(seed),
                   std::move(fold));
 }
 
-template<class Reducer,
-         class Reduce = detail::Reduce<Reducer>>
+template <class Reducer, class Reduce = detail::Reduce<Reducer>>
 Reduce reduce(Reducer reducer = Reducer()) {
   return Reduce(std::move(reducer));
 }
 
-template<class Selector = Identity,
-         class Min = detail::Min<Selector, Less>>
+template <class Selector = Identity, class Min = detail::Min<Selector, Less>>
 Min minBy(Selector selector = Selector()) {
   return Min(std::move(selector));
 }
 
-template<class Selector,
-         class MaxBy = detail::Min<Selector, Greater>>
+template <class Selector, class MaxBy = detail::Min<Selector, Greater>>
 MaxBy maxBy(Selector selector = Selector()) {
   return MaxBy(std::move(selector));
 }
 
-template<class Collection,
-         class Collect = detail::Collect<Collection>>
+template <class Collection, class Collect = detail::Collect<Collection>>
 Collect as() {
   return Collect();
 }
 
-template<template<class, class> class Container = std::vector,
-         template<class> class Allocator = std::allocator,
-         class Collect = detail::CollectTemplate<Container, Allocator>>
+template <
+    template <class, class> class Container = std::vector,
+    template <class> class Allocator = std::allocator,
+    class Collect = detail::CollectTemplate<Container, Allocator>>
 Collect as() {
   return Collect();
 }
 
-template<class Collection,
-         class Append = detail::Append<Collection>>
+template <class Collection, class Append = detail::Append<Collection>>
 Append appendTo(Collection& collection) {
   return Append(&collection);
 }
 
-template<class Needle,
-         class Contains = detail::Contains<typename std::decay<Needle>::type>>
+template <
+    class Needle,
+    class Contains = detail::Contains<typename std::decay<Needle>::type>>
 Contains contains(Needle&& needle) {
   return Contains(std::forward<Needle>(needle));
 }
 
-template<class Exception,
-         class ErrorHandler,
-         class GuardImpl =
-           detail::GuardImpl<
-             Exception,
-             typename std::decay<ErrorHandler>::type>>
+template <
+    class Exception,
+    class ErrorHandler,
+    class GuardImpl =
+        detail::GuardImpl<Exception, typename std::decay<ErrorHandler>::type>>
 GuardImpl guard(ErrorHandler&& handler) {
   return GuardImpl(std::forward<ErrorHandler>(handler));
 }
 
-}} // folly::gen
+template <
+    class Fallback,
+    class UnwrapOr = detail::UnwrapOr<typename std::decay<Fallback>::type>>
+UnwrapOr unwrapOr(Fallback&& fallback) {
+  return UnwrapOr(std::forward<Fallback>(fallback));
+}
+
+} // namespace gen
+} // namespace folly
 
 #include <folly/gen/Base-inl.h>
-
-#endif // FOLLY_GEN_BASE_H