On Thursday, 8 November 2012 at 09:18:54 UTC, Jonathan M Davis wrote:
In the case of retro, I think that it would good to have source exposed for std.container's use. It's easy for std.container to understand what retro's supposed to do, and use it accordingly, and I think that it would be silly for it have to call retro on the retroed range to do that. I do agree however that
in general, it doesn't make sense to access source.

Yes, accessing the original range is useful, but AFAIK, container doesn't use retro in any way. It does it with take (which also has a source field). For take, there is no way to extract the source other than with a specialized function.

regarding retro, I find it silly it has a "source" field at all, when the original could just be retrieved using retro again (and just as efficiently). I don't see any way using source over retro could be useful to anyone at all, except for actually implementing retro().retro() itself (in which case a _source would have done just as well).

As for

The problem though is in the way the documentation "The original range can be accessed by using the source property" and "Applying retro twice to the same range yields the original range": Looks like we forgot to notice these two sentences are contradicting.

I don't see anything contradictory at all. If you call retro on a retroed range, you get the original. If you access source, you get the original.
Where's the contradiction?

In "If you access source, you get the original". This is only true if the "The original" is not itslef already a retro. This mind sound silly, but you may not have control of this. For example,

For example, imagine you want a find function that searches from the end, and returns the result of everything before the match:

//----
import std.stdio;
import std.algorithm;
import std.range;

auto findBefore(R)(R r, int n)
{
    auto a = r.retro();
    auto result = a.find(n);
static assert(is(typeof(result) == typeof(r.retro()))); //result is a retro
    return result.source; //Error: undefined identifier 'source'
}

void main()
{
    auto a = [0, 1, 2, 3, 4, 5];
    a.findBefore(3).writeln(); //expect [1, 2, 3]
    a.retro().findBefore(3).writeln(); //expect [5, 4, 3]

    auto b = indexed([2, 1, 3, 0, 4, 5], [3, 1, 0, 2, 4, 5]);
    assert(b.equal(a)); // b is [0, 1, 2, 3, 4, 5]
b.retro().findBefore(3).writeln(); // produces [2, 1, 3, 0, 4, 5]...
}
//----
In "findBefore3", one should expect getting back the "original range", but that is not the case. However, using "return result.retro()"; works quite well.

Things get even stranger if the underlying range also as a "source" filed itself (because of the auto return type).

Both the issues can be fixed with "return result.source;"

--------
I don't think there is anything to be gained using "source". I don't think it would be worth deprecating it either, and it is not a huge issue, but I think the documentation should favor the use of double retro over source, or even mention source at all.

Less surprises is always better.

Reply via email to