Commit a1107271 authored by Joe Richey's avatar Joe Richey Committed by Sara Golemon

Actually denote when we have infinite generators

Summary: Before we didn't do anything at all with the ::infinite value for our
generators, now all the sources operators and sinks are properly notated. The
one signifcant change regarding what is allowed concerns 'cycle' which now (when
called with no arguments) always produces an infinite generator. This is fine
for all but the weirdest of generators fed into cycle.

Reviewed By: @ddrcoder

Differential Revision: D2240328
parent 43d53e06
This diff is collapsed.
...@@ -181,6 +181,13 @@ class GenImpl : public FBounded<Self> { ...@@ -181,6 +181,13 @@ class GenImpl : public FBounded<Self> {
// Child classes should override if the sequence generated is *definitely* // Child classes should override if the sequence generated is *definitely*
// infinite. 'infinite' may be false_type for some infinite sequences // infinite. 'infinite' may be false_type for some infinite sequences
// (due the the Halting Problem). // (due the the Halting Problem).
//
// In general, almost all sources are finite (only seq(n) produces an infinite
// source), almost all operators keep the finiteness of the source (only cycle
// makes an infinite generator from a finite one, only until and take make a
// finite generator from an infinite one, and concat needs both the inner and
// outer generators to be finite to make a finite one), and most sinks
// cannot accept and infinite generators (first being the expection).
static constexpr bool infinite = false; static constexpr bool infinite = false;
}; };
......
...@@ -577,6 +577,37 @@ TEST(Gen, DistinctMove) { // 0 1 4 9 6 5 6 9 4 1 0 ...@@ -577,6 +577,37 @@ TEST(Gen, DistinctMove) { // 0 1 4 9 6 5 6 9 4 1 0
EXPECT_EQ(expected, actual); EXPECT_EQ(expected, actual);
} }
TEST(Gen, DistinctInfinite) {
// distinct should be able to handle an infinite sequence, provided that, of
// of cource, is it eventually made finite before returning the result.
auto expected = seq(0) | take(5) | as<vector>(); // 0 1 2 3 4
auto actual =
seq(0) // 0 1 2 3 4 5 6 7 ...
| mapped([](int i) { return i / 2; }) // 0 0 1 1 2 2 3 3 ...
| distinct // 0 1 2 3 4 5 6 7 ...
| take(5) // 0 1 2 3 4
| as<vector>();
EXPECT_EQ(expected, actual);
}
TEST(Gen, DistinctByInfinite) {
// Similarly to the DistinctInfinite test case, distinct by should be able to
// handle infinite sequences. Note that depending on how many values we take()
// at the end, the sequence may infinite loop. This is fine becasue we cannot
// solve the halting problem.
auto expected = vector<int>{1, 2};
auto actual =
seq(1) // 1 2 3 4 5 6 7 8 ...
| distinctBy([](int i) { return i % 2; }) // 1 2 (but might by infinite)
| take(2) // 1 2
| as<vector>();
// Note that if we had take(3), this would infinite loop
EXPECT_EQ(expected, actual);
}
TEST(Gen, MinBy) { TEST(Gen, MinBy) {
EXPECT_EQ(7, seq(1, 10) EXPECT_EQ(7, seq(1, 10)
| minBy([](int i) -> double { | minBy([](int i) -> double {
...@@ -743,21 +774,17 @@ TEST(Gen, Get) { ...@@ -743,21 +774,17 @@ TEST(Gen, Get) {
} }
TEST(Gen, notEmpty) { TEST(Gen, notEmpty) {
EXPECT_TRUE(seq(0) | notEmpty);
EXPECT_TRUE(seq(0, 1) | notEmpty); EXPECT_TRUE(seq(0, 1) | notEmpty);
EXPECT_TRUE(just(1) | notEmpty); EXPECT_TRUE(just(1) | notEmpty);
EXPECT_FALSE(gen::range(0, 0) | notEmpty); EXPECT_FALSE(gen::range(0, 0) | notEmpty);
EXPECT_FALSE(from({1}) | take(0) | notEmpty); EXPECT_FALSE(from({1}) | take(0) | notEmpty);
EXPECT_TRUE(seq(1, 3) | cycle | notEmpty);
} }
TEST(Gen, isEmpty) { TEST(Gen, isEmpty) {
EXPECT_FALSE(seq(0) | isEmpty);
EXPECT_FALSE(seq(0, 1) | isEmpty); EXPECT_FALSE(seq(0, 1) | isEmpty);
EXPECT_FALSE(just(1) | isEmpty); EXPECT_FALSE(just(1) | isEmpty);
EXPECT_TRUE(gen::range(0, 0) | isEmpty); EXPECT_TRUE(gen::range(0, 0) | isEmpty);
EXPECT_TRUE(from({1}) | take(0) | isEmpty); EXPECT_TRUE(from({1}) | take(0) | isEmpty);
EXPECT_FALSE(seq(1, 3) | cycle | isEmpty);
} }
TEST(Gen, Any) { TEST(Gen, Any) {
...@@ -1018,7 +1045,8 @@ TEST(Gen, Cycle) { ...@@ -1018,7 +1045,8 @@ TEST(Gen, Cycle) {
}; };
auto s = countdown; auto s = countdown;
EXPECT_EQ((vector<int> { 1, 2, 3, 1, 2, 1}), EXPECT_EQ((vector<int> { 1, 2, 3, 1, 2, 1}),
s | cycle | as<vector>()); s | cycle | take(7) | as<vector>());
// take necessary as cycle returns an infinite generator
} }
} }
......
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