Commit 0e21224b authored by Tom Jackson's avatar Tom Jackson Committed by Jordan DeLong

all(), better any()

Summary: TSIA

Test Plan: Unit tests

Reviewed By: tulloch@fb.com

FB internal diff: D701890
parent 04223d27
...@@ -528,10 +528,10 @@ class Yield : public GenImpl<Value, Yield<Value, Source>> { ...@@ -528,10 +528,10 @@ class Yield : public GenImpl<Value, Yield<Value, Source>> {
*/ */
template<class Predicate> template<class Predicate>
class Map : public Operator<Map<Predicate>> { class Map : public Operator<Map<Predicate>> {
Predicate predicate_; Predicate pred_;
public: public:
explicit Map(const Predicate& predicate = Predicate()) explicit Map(const Predicate& pred = Predicate())
: predicate_(predicate) : pred_(pred)
{ } { }
template<class Value, template<class Value,
...@@ -566,14 +566,14 @@ class Map : public Operator<Map<Predicate>> { ...@@ -566,14 +566,14 @@ class Map : public Operator<Map<Predicate>> {
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const { Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), predicate_); return Gen(std::move(source.self()), pred_);
} }
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
Gen compose(const GenImpl<Value, Source>& source) const { 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>> { ...@@ -590,10 +590,10 @@ class Map : public Operator<Map<Predicate>> {
*/ */
template<class Predicate> template<class Predicate>
class Filter : public Operator<Filter<Predicate>> { class Filter : public Operator<Filter<Predicate>> {
Predicate predicate_; Predicate pred_;
public: public:
explicit Filter(const Predicate& predicate) explicit Filter(const Predicate& pred = Predicate())
: predicate_(predicate) : pred_(pred)
{ } { }
template<class Value, template<class Value,
...@@ -629,14 +629,14 @@ class Filter : public Operator<Filter<Predicate>> { ...@@ -629,14 +629,14 @@ class Filter : public Operator<Filter<Predicate>> {
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const { Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), predicate_); return Gen(std::move(source.self()), pred_);
} }
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
Gen compose(const GenImpl<Value, Source>& source) const { 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>> { ...@@ -651,10 +651,10 @@ class Filter : public Operator<Filter<Predicate>> {
*/ */
template<class Predicate> template<class Predicate>
class Until : public Operator<Until<Predicate>> { class Until : public Operator<Until<Predicate>> {
Predicate predicate_; Predicate pred_;
public: public:
explicit Until(const Predicate& predicate) explicit Until(const Predicate& pred = Predicate())
: predicate_(predicate) : pred_(pred)
{ } { }
template<class Value, template<class Value,
...@@ -681,14 +681,14 @@ class Until : public Operator<Until<Predicate>> { ...@@ -681,14 +681,14 @@ class Until : public Operator<Until<Predicate>> {
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const { Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), predicate_); return Gen(std::move(source.self()), pred_);
} }
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
Gen compose(const GenImpl<Value, Source>& source) const { 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>> { ...@@ -935,6 +935,7 @@ class Composed : public Operator<Composed<First, Second>> {
Second second_; Second second_;
public: public:
Composed() {} Composed() {}
Composed(First first, Second second) Composed(First first, Second second)
: first_(std::move(first)) : first_(std::move(first))
, second_(std::move(second)) {} , second_(std::move(second)) {}
...@@ -1027,11 +1028,16 @@ class First : public Operator<First> { ...@@ -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: * This type is primarily used through the 'any' static value, like:
* *
* bool any20xPrimes = seq(200, 210) | filter(isPrime) | any; * 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> { class Any : public Operator<Any> {
public: public:
...@@ -1047,6 +1053,50 @@ class Any : public Operator<Any> { ...@@ -1047,6 +1053,50 @@ class Any : public Operator<Any> {
}; };
return 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;
}
}; };
/** /**
......
...@@ -223,6 +223,13 @@ template<class Seed, ...@@ -223,6 +223,13 @@ template<class Seed,
class Fold> class Fold>
class FoldLeft; class FoldLeft;
class First;
class Any;
template<class Predicate>
class All;
template<class Reducer> template<class Reducer>
class Reduce; class Reduce;
...@@ -342,14 +349,20 @@ Map map(const Predicate& pred = Predicate()) { ...@@ -342,14 +349,20 @@ Map map(const Predicate& pred = Predicate()) {
template<class Predicate, template<class Predicate,
class Filter = detail::Filter<Predicate>> class Filter = detail::Filter<Predicate>>
Filter filter(const Predicate& pred = Predicate()) { Filter filter(Predicate pred = Predicate()) {
return Filter(pred); 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, template<class Predicate,
class Until = detail::Until<Predicate>> class Until = detail::Until<Predicate>>
Until until(const Predicate& pred = Predicate()) { Until until(Predicate pred = Predicate()) {
return Until(pred); return Until(std::move(pred));
} }
template<class Selector, template<class Selector,
......
...@@ -416,11 +416,24 @@ TEST(Gen, Get) { ...@@ -416,11 +416,24 @@ TEST(Gen, Get) {
TEST(Gen, Any) { TEST(Gen, Any) {
EXPECT_TRUE(seq(0) | any); EXPECT_TRUE(seq(0) | any);
EXPECT_TRUE(seq(0, 1) | 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_TRUE(from({1}) | any);
EXPECT_FALSE(range(0, 0) | any); EXPECT_FALSE(range(0, 0) | any);
EXPECT_FALSE(from({1}) | take(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) { TEST(Gen, Yielders) {
auto gen = GENERATOR(int) { auto gen = GENERATOR(int) {
for (int i = 1; i <= 5; ++i) { for (int i = 1; i <= 5; ++i) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment