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>> {
*/
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;
}
};
/**
......
......@@ -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,14 +349,20 @@ 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,
......
......@@ -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) {
......
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