Unlisted bug in Map.save and a few stylistic changes

This commit is contained in:
Andrei Alexandrescu 2010-07-04 21:04:48 +00:00
parent 875d77e732
commit 4347cae9f5

View file

@ -53,7 +53,6 @@ import std.array, std.container, std.contracts, std.conv, std.date,
version(unittest) version(unittest)
{ {
import std.random, std.stdio, std.string; import std.random, std.stdio, std.string;
mixin(dummyRanges); mixin(dummyRanges);
} }
@ -118,20 +117,20 @@ struct Map(alias fun, Range) if (isInputRange!(Range))
Range _input; Range _input;
ElementType _cache; ElementType _cache;
static if(isBidirectionalRange!(Range)) { static if (isBidirectionalRange!(Range)) {
// Using a second cache would lead to at least 1 extra function evaluation // Using a second cache would lead to at least 1 extra function evaluation
// and wasted space when 99% of the time this range will only be iterated // and wasted space when 99% of the time this range will only be iterated
// over in the forward direction. Use a bool to determine whether cache // over in the forward direction. Use a bool to determine whether cache
// is front or back instead. // is front or back instead.
bool cacheIsBack; bool cacheIsBack_;
private void fillCacheBack() { private void fillCacheBack() {
if (!_input.empty) _cache = fun(_input.back); if (!_input.empty) _cache = fun(_input.back);
cacheIsBack = true; cacheIsBack_ = true;
} }
@property ElementType back() { @property ElementType back() {
if(!cacheIsBack) { if (!cacheIsBack_) {
fillCacheBack(); fillCacheBack();
} }
return _cache; return _cache;
@ -147,7 +146,7 @@ struct Map(alias fun, Range) if (isInputRange!(Range))
if (!_input.empty) _cache = fun(_input.front); if (!_input.empty) _cache = fun(_input.front);
static if(isBidirectionalRange!(Range)) { static if(isBidirectionalRange!(Range)) {
cacheIsBack = false; cacheIsBack_ = false;
} }
} }
@ -156,7 +155,7 @@ struct Map(alias fun, Range) if (isInputRange!(Range))
fillCache; fillCache;
} }
static if(isInfinite!Range) { static if (isInfinite!Range) {
// Propagate infinite-ness. // Propagate infinite-ness.
enum bool empty = false; enum bool empty = false;
} else { } else {
@ -167,33 +166,33 @@ struct Map(alias fun, Range) if (isInputRange!(Range))
void popFront() { void popFront() {
_input.popFront; _input.popFront;
fillCache; fillCache();
} }
@property ElementType front() { @property ElementType front() {
static if(isBidirectionalRange!(Range)) { static if (isBidirectionalRange!(Range)) {
if(cacheIsBack) { if (cacheIsBack_) {
fillCache(); fillCache();
} }
} }
return _cache; return _cache;
} }
static if(isRandomAccessRange!Range) { static if (isRandomAccessRange!Range) {
ElementType opIndex(size_t index) { ElementType opIndex(size_t index) {
return fun(_input[index]); return fun(_input[index]);
} }
} }
// hasLength is busted, Bug 2873 // hasLength is busted, Bug 2873
static if(is(typeof(_input.length) : size_t) static if (is(typeof(_input.length) : size_t)
|| is(typeof(_input.length()) : size_t)) { || is(typeof(_input.length()) : size_t)) {
@property size_t length() { @property size_t length() {
return _input.length; return _input.length;
} }
} }
static if(hasSlicing!(Range)) { static if (hasSlicing!(Range)) {
typeof(this) opSlice(size_t lowerBound, size_t upperBound) { typeof(this) opSlice(size_t lowerBound, size_t upperBound) {
return typeof(this)(_input[lowerBound..upperBound]); return typeof(this)(_input[lowerBound..upperBound]);
} }
@ -202,10 +201,7 @@ struct Map(alias fun, Range) if (isInputRange!(Range))
static if (isForwardRange!Range) static if (isForwardRange!Range)
@property Map save() @property Map save()
{ {
Map result; return this;
result._input = _input.save;
result._cache = _cache;
return result;
} }
} }
@ -219,8 +215,10 @@ unittest
assert(equal(map!("a * a")(chain(arr1, arr2)), [ 1, 4, 9, 16, 25, 36 ][])); assert(equal(map!("a * a")(chain(arr1, arr2)), [ 1, 4, 9, 16, 25, 36 ][]));
// Test the caching stuff. // Test the caching stuff.
auto squares2 = squares; assert(squares.back == 16);
auto squares2 = squares.save;
assert(squares2.back == 16); assert(squares2.back == 16);
assert(squares2.front == 1); assert(squares2.front == 1);
squares2.popFront; squares2.popFront;
assert(squares2.front == 4); assert(squares2.front == 4);
@ -578,7 +576,7 @@ struct Filter(alias pred, Range) if (isInputRange!(Range))
return this; return this;
} }
static if(isInfinite!Range) { static if (isInfinite!Range) {
enum bool empty = false; // Propagate infiniteness. enum bool empty = false; // Propagate infiniteness.
} else { } else {
bool empty() { return _input.empty; } bool empty() { return _input.empty; }
@ -610,7 +608,7 @@ struct Filter(alias pred, Range) if (isInputRange!(Range))
} }
static if(isForwardRange!Range) static if (isForwardRange!Range)
{ {
@property typeof(this) save() @property typeof(this) save()
{ {
@ -645,11 +643,11 @@ unittest
auto f = filter!"a & 1"(d); auto f = filter!"a & 1"(d);
assert(equal(f, [1,3,5,7,9])); assert(equal(f, [1,3,5,7,9]));
static if(isForwardRange!DummyType) { static if (isForwardRange!DummyType) {
static assert(isForwardRange!(typeof(f))); static assert(isForwardRange!(typeof(f)));
} }
static if(isBidirectionalRange!DummyType) { static if (isBidirectionalRange!DummyType) {
static assert(isBidirectionalRange!(typeof(f))); static assert(isBidirectionalRange!(typeof(f)));
assert(equal(retro(f), [9,7,5,3,1])); assert(equal(retro(f), [9,7,5,3,1]));
} }
@ -876,7 +874,7 @@ public:
// computeBack(); // computeBack();
} }
static if(isInfinite!Range) static if (isInfinite!Range)
{ {
enum bool empty = false; enum bool empty = false;
} else } else
@ -1011,7 +1009,7 @@ public:
return _input[0 .. _frontLength]; return _input[0 .. _frontLength];
} }
static if(isInfinite!Range) static if (isInfinite!Range)
{ {
enum bool empty = false; // Propagate infiniteness enum bool empty = false; // Propagate infiniteness
} }
@ -1158,7 +1156,7 @@ struct Splitter(alias isTerminator, Range,
} }
} }
static if(isInfinite!Range) static if (isInfinite!Range)
{ {
enum bool empty = false; // Propagate infiniteness. enum bool empty = false; // Propagate infiniteness.
} }
@ -1281,7 +1279,7 @@ struct Uniq(alias pred, R)
@property ElementType!(R) front() { return _input.front; } @property ElementType!(R) front() { return _input.front; }
static if(isBidirectionalRange!R) static if (isBidirectionalRange!R)
{ {
void popBack() void popBack()
{ {
@ -1296,7 +1294,7 @@ struct Uniq(alias pred, R)
@property ElementType!(R) back() { return _input.back; } @property ElementType!(R) back() { return _input.back; }
} }
static if(isInfinite!R) static if (isInfinite!R)
{ {
enum bool empty = false; // Propagate infiniteness. enum bool empty = false; // Propagate infiniteness.
} }
@ -1306,7 +1304,7 @@ struct Uniq(alias pred, R)
} }
static if(isForwardRange!R) { static if (isForwardRange!R) {
@property typeof(this) save() { @property typeof(this) save() {
return typeof(this)(_input.save); return typeof(this)(_input.save);
} }
@ -1333,7 +1331,7 @@ unittest
static assert(d.rt == RangeType.Input || isForwardRange!(typeof(u))); static assert(d.rt == RangeType.Input || isForwardRange!(typeof(u)));
static if(d.rt >= RangeType.Bidirectional) { static if (d.rt >= RangeType.Bidirectional) {
assert(equal(retro(u), [10,9,8,7,6,5,4,3,2,1])); assert(equal(retro(u), [10,9,8,7,6,5,4,3,2,1]));
} }
} }
@ -1387,7 +1385,7 @@ struct Group(alias pred, R) if (isInputRange!R)
} }
} }
static if(isInfinite!R) static if (isInfinite!R)
{ {
enum bool empty = false; // Propagate infiniteness. enum bool empty = false; // Propagate infiniteness.
} }
@ -1405,7 +1403,7 @@ struct Group(alias pred, R) if (isInputRange!R)
return _current; return _current;
} }
static if(isForwardRange!R) { static if (isForwardRange!R) {
@property typeof(this) save() { @property typeof(this) save() {
typeof(this) ret; typeof(this) ret;
ret._input = this._input.save; ret._input = this._input.save;