all(), better any()
authorTom Jackson <tjackson@fb.com>
Thu, 7 Feb 2013 18:18:15 +0000 (10:18 -0800)
committerJordan DeLong <jdelong@fb.com>
Tue, 19 Mar 2013 00:06:58 +0000 (17:06 -0700)
Summary: TSIA

Test Plan: Unit tests

Reviewed By: tulloch@fb.com

FB internal diff: D701890

folly/experimental/Gen-inl.h
folly/experimental/Gen.h
folly/experimental/test/GenTest.cpp

index 6937fbb64ec2ad9943c7a6a3f4fad8b7773d2825..134783958d0b18c50714de85f5457a8b85482644 100644 (file)
@@ -528,10 +528,10 @@ class Yield : public GenImpl<Value, Yield<Value, Source>> {
  */
 template<class Predicate>
 class Map : public Operator<Map<Predicate>> {
-  Predicate predicate_;
+  Predicate pred_;
  public:
-  explicit Map(const Predicate& predicate = Predicate())
-    : predicate_(predicate)
+  explicit Map(const Predicate& pred = Predicate())
+    : pred_(pred)
   { }
 
   template<class Value,
@@ -566,14 +566,14 @@ class Map : public Operator<Map<Predicate>> {
            class Value,
            class Gen = Generator<Value, Source>>
   Gen compose(GenImpl<Value, Source>&& source) const {
-    return Gen(std::move(source.self()), predicate_);
+    return Gen(std::move(source.self()), pred_);
   }
 
   template<class Source,
            class Value,
            class Gen = Generator<Value, Source>>
   Gen compose(const GenImpl<Value, Source>& source) const {
-    return Gen(source.self(), predicate_);
+    return Gen(source.self(), pred_);
   }
 };
 
@@ -590,10 +590,10 @@ class Map : public Operator<Map<Predicate>> {
  */
 template<class Predicate>
 class Filter : public Operator<Filter<Predicate>> {
-  Predicate predicate_;
+  Predicate pred_;
  public:
-  explicit Filter(const Predicate& predicate)
-    : predicate_(predicate)
+  explicit Filter(const Predicate& pred = Predicate())
+    : pred_(pred)
   { }
 
   template<class Value,
@@ -629,14 +629,14 @@ class Filter : public Operator<Filter<Predicate>> {
            class Value,
            class Gen = Generator<Value, Source>>
   Gen compose(GenImpl<Value, Source>&& source) const {
-    return Gen(std::move(source.self()), predicate_);
+    return Gen(std::move(source.self()), pred_);
   }
 
   template<class Source,
            class Value,
            class Gen = Generator<Value, Source>>
   Gen compose(const GenImpl<Value, Source>& source) const {
-    return Gen(source.self(), predicate_);
+    return Gen(source.self(), pred_);
   }
 };
 
@@ -651,10 +651,10 @@ class Filter : public Operator<Filter<Predicate>> {
  */
 template<class Predicate>
 class Until : public Operator<Until<Predicate>> {
-  Predicate predicate_;
+  Predicate pred_;
  public:
-  explicit Until(const Predicate& predicate)
-    : predicate_(predicate)
+  explicit Until(const Predicate& pred = Predicate())
+    : pred_(pred)
   { }
 
   template<class Value,
@@ -681,14 +681,14 @@ class Until : public Operator<Until<Predicate>> {
            class Value,
            class Gen = Generator<Value, Source>>
   Gen compose(GenImpl<Value, Source>&& source) const {
-    return Gen(std::move(source.self()), predicate_);
+    return Gen(std::move(source.self()), pred_);
   }
 
   template<class Source,
            class Value,
            class Gen = Generator<Value, Source>>
   Gen compose(const GenImpl<Value, Source>& source) const {
-    return Gen(source.self(), predicate_);
+    return Gen(source.self(), pred_);
   }
 };
 
@@ -935,6 +935,7 @@ class Composed : public Operator<Composed<First, Second>> {
   Second second_;
  public:
   Composed() {}
+
   Composed(First first, Second second)
     : first_(std::move(first))
     , second_(std::move(second)) {}
@@ -1027,11 +1028,16 @@ class First : public Operator<First> {
 
 
 /**
- * Any - For determining whether any values are contained in a sequence.
+ * Any - For determining whether any values in a sequence satisfy a predicate.
  *
  * This type is primarily used through the 'any' static value, like:
  *
  *   bool any20xPrimes = seq(200, 210) | filter(isPrime) | any;
+ *
+ * Note that it may also be used like so:
+ *
+ *   bool any20xPrimes = seq(200, 210) | any(isPrime);
+ *
  */
 class Any : public Operator<Any> {
  public:
@@ -1047,6 +1053,50 @@ class Any : public Operator<Any> {
     };
     return any;
   }
+
+  /**
+   * Convenience function for use like:
+   *
+   *  bool found = gen | any([](int i) { return i * i > 100; });
+   */
+  template<class Predicate,
+           class Filter = Filter<Predicate>,
+           class Composed = Composed<Filter, Any>>
+  Composed operator()(Predicate pred) const {
+    return Composed(Filter(std::move(pred)), Any());
+  }
+};
+
+/**
+ * All - For determining whether all values in a sequence satisfy a predicate.
+ *
+ * This type is primarily used through the 'any' static value, like:
+ *
+ *   bool valid = from(input) | all(validate);
+ *
+ * Note: Passing an empty sequence through 'all()' will always return true.
+ */
+template<class Predicate>
+class All : public Operator<All<Predicate>> {
+  Predicate pred_;
+ public:
+  explicit All(const Predicate& pred = Predicate())
+    : pred_(pred)
+  { }
+
+  template<class Source,
+           class Value>
+  bool compose(const GenImpl<Value, Source>& source) const {
+    bool all = true;
+    source | [&](Value v) -> bool {
+      if (!pred_(std::forward<Value>(v))) {
+        all = false;
+        return false;
+      }
+      return true;
+    };
+    return all;
+  }
 };
 
 /**
index 444fb8ef625803b57723c73761bc18ae378739a0..b44cfde0d421ff55cc425cd5a4bf825c22c92799 100644 (file)
@@ -223,6 +223,13 @@ template<class Seed,
          class Fold>
 class FoldLeft;
 
+class First;
+
+class Any;
+
+template<class Predicate>
+class All;
+
 template<class Reducer>
 class Reduce;
 
@@ -342,21 +349,27 @@ Map map(const Predicate& pred = Predicate()) {
 
 template<class Predicate,
          class Filter = detail::Filter<Predicate>>
-Filter filter(const Predicate& pred = Predicate()) {
-  return Filter(pred);
+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 Predicate,
          class Until = detail::Until<Predicate>>
-Until until(const Predicate& pred = Predicate()) {
-  return Until(pred);
+Until until(Predicate pred = Predicate()) {
+  return Until(std::move(pred));
 }
 
 template<class Selector,
          class Comparer = Less,
          class Order = detail::Order<Selector, Comparer>>
 Order orderBy(const Selector& selector,
-                const Comparer& comparer = Comparer()) {
+              const Comparer& comparer = Comparer()) {
   return Order(selector, comparer);
 }
 
index 355cd41def88e0613b703dbc5370dc8f4bb60ad0..4e08fbd0af0335e6d454de84550e785565ba753a 100644 (file)
@@ -416,11 +416,24 @@ TEST(Gen, Get) {
 TEST(Gen, Any) {
   EXPECT_TRUE(seq(0) | any);
   EXPECT_TRUE(seq(0, 1) | any);
+  EXPECT_TRUE(seq(0, 10) | any([](int i) { return i == 7; }));
+  EXPECT_FALSE(seq(0, 10) | any([](int i) { return i == 11; }));
+
   EXPECT_TRUE(from({1}) | any);
   EXPECT_FALSE(range(0, 0) | any);
   EXPECT_FALSE(from({1}) | take(0) | any);
 }
 
+TEST(Gen, All) {
+  EXPECT_TRUE(seq(0, 10) | all([](int i) { return i < 11; }));
+  EXPECT_FALSE(seq(0, 10) | all([](int i) { return i < 5; }));
+  EXPECT_FALSE(seq(0) | all([](int i) { return i < 10; }));
+
+  // empty lists satisfies all
+  EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i < 50; }));
+  EXPECT_TRUE(seq(0) | take(0) | all([](int i) { return i > 50; }));
+}
+
 TEST(Gen, Yielders) {
   auto gen = GENERATOR(int) {
     for (int i = 1; i <= 5; ++i) {