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

Reply via email to