Proposal to deprecate "retro.source"

Jonathan M Davis jmdavisProg at gmx.com
Thu Nov 8 10:20:18 PST 2012


On Thursday, November 08, 2012 10:56:38 monarch_dodra wrote:
> 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.

std.container doesn't use retro right now, but it really should (though that 
would require externalizing retro's return type). For instance, what would you 
do if you had to remove the last five elemets from a DList? You can't simply 
take the last 5 and pass that to remove with something like take(retro(list[], 
5)) or retro(take(retro(list[], 5))), because the resulting type is 
unrecognized by remove. You're forced to do something like

list.remove(popFrontN(list[], walkLength(list[]) - 5));

which is highly inefficient.

> 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).

Andrei has expressed interest in having _all_ ranges (or at least a sizeable 
number of them) expose source. That being the case, using retro to get at the 
original doesn't really make sense. That's what source is for. retro naturally 
returns the original type when you retro it again, because it avoids type 
proliferation, but that's specific to retro.

Now, how useful source will ultimately be in generic code which doesn't know 
exactly what range type it's dealing with, I don't know. It may ultimately be 
pretty much useless. But even if you have to know what the type is to use it 
appopriately, since they'd generally be exposing the original range through 
source, it makes sense that retro would do the same.

> > 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,

It makes perfect sense that retro would return the same type when retro is 
called on an already retroed range. And that's the _only_ case where source 
wouldn't exist. The real problem with relying on source from the type returned 
by retro is the fact the result could be _another_ range which exposes source 
rather than retro - e.g. retro(retro(take(range, 5))). The docs aren't really 
incorrect in either case. It's just that in that one case, the result is a 
different type than the rest.

I have no problem with removing mention of source from the docs. I don't think 
that it should be used normally. I do think that it makes sense to have it, 
but it makes sense primarily as part of the general approach of giving ranges 
source members. Certainly, using source directly after a call to retro makes 
no sense. For using source to _ever_ make sense (in general, not just with 
retro), you need to know that you're dealing with a wrapper range. So, using 
source immediately after having called a function which potentially returns a 
wrapper range doesn't really make sense. It makes sense when you already know 
that you're dealing with a wrapper range (e.g. you already know that it's a 
Take!Whatever), and even then, I think that it primarily makes sense when 
you're looking for a specific type that's being wrapped (as is the case with 
std.container) rather than when dealing with a generic type which was wrapped.

- Jonathan M Davis


More information about the Digitalmars-d mailing list