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
