Preferred behavior of take() with ranges (value vs reference range)

Jon D via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Nov 8 18:14:55 PST 2015


Just started looking at D, very promising!

One of the first programs I constructed involved infinite 
sequences. A design question  that showed up is whether to 
construct the range as a struct/value, or class/reference. It 
appears that structs/values are more the norm, but there are 
exceptions, notably refRange. I'm wondering if there are any 
community best practices or guidelines in this area.

One key difference is the behavior of take(). If the range is a 
value/struct, take() does not consume elements. If it's a 
ref/class, it does consume elements. From a consistency 
perspective, it'd seem useful if the behavior was consistent as 
much as possible.

Here's an example of the behavior differences below. It uses 
refRange, but same behavior occurs if the range is created as a 
class rather than a struct.

import std.range;
import std.algorithm;

void main() {
     auto fib1 = recurrence!((a,n) => a[n-1] + a[n-2])(1, 1);
     auto fib2 = recurrence!((a,n) => a[n-1] + a[n-2])(1, 1);
     auto fib3 = refRange(&fib2);

     // Struct/value based range - take() does not consume elements
     assert(fib1.take(7).equal([1, 1, 2, 3, 5, 8, 13]));
     assert(fib1.take(7).equal([1, 1, 2, 3, 5, 8, 13]));
     fib1.popFrontN(7);
     assert(fib1.take(7).equal([21, 34, 55, 89, 144, 233, 377]));

     // Reference range (fib3) - take() consumes elements
     assert(fib2.take(7).equal([1, 1, 2, 3, 5, 8, 13]));
     assert(fib3.take(7).equal([1, 1, 2, 3, 5, 8, 13]));
     assert(fib3.take(7).equal([21, 34, 55, 89, 144, 233, 377]));
     assert(fib2.take(7).equal([610, 987, 1597, 2584, 4181, 6765, 
10946]));
     assert(fib2.take(7).equal([610, 987, 1597, 2584, 4181, 6765, 
10946]));
}

--Jon


More information about the Digitalmars-d-learn mailing list