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.