std.range.cacheFront proposal&working code: wraps a range to enforce front is called only once

Jonathan M Davis jmdavisProg at gmx.com
Sun Oct 27 00:40:12 PDT 2013


On Thursday, October 24, 2013 23:09:58 Timothee Cour wrote:
> On Thu, Oct 24, 2013 at 12:50 PM, Jonathan M Davis 
> > , then creating a custom range is exactly what you should be doing,
> 
> why make user reimplement the wheel each time with a custom range when a
> generic solution (such as above, maybe could be improved) works ?

Because you're trying to do something that goes against the design of map and 
ranges. Sure, it might work with the current implementation, and you can do 
stlike cacheFront to try and guarantee that front is only called once so that 
your solution will work, but you're contorting the design in order to do 
something that goes against what it was designed for, and that's asking for 
problems.

Regardless, you're free to do what you want in your code, but that doesn't 
mean that it makes any sense for that to make it into the standard library. 
The standard library should have solutions which conform with its existing 
design rather than which try and work around it.

> > and the logic for the pre and post operations should go in popFront.
> 
> how can a *pre*-operation go in popFront, which occurs *after* front
> (without significant gymnastics) ?

You just make it so that it occurs when the range is constructed, and then it 
can occur after the previous front. You might have to look at what you're 
doing slightly differently to move operations from front to popFront, but in my 
experience, it really isn't all that hard, and you usually end up with better 
code that way.

> > Having side effects in front is just begging for problems, and it's not at
> > all what map is designed for. And honestly, if
> > your popFront isn't pure as well, and the side effects that you're doing
> > affect
> > something outside of the range, then I would suggest that you not use
> > ranges
> > for what you're doing, because that violates their functional nature.
> 
> That's an arbitrary restriction. I've faced many situations where I could
> use the full power of range based algorithms while not restricting myself
> to purely functional code (necessary side effects). With proper care it can
> be done. Again, no need to reimplement standard algorithms just because of
> some impure lambdas.

Again, what you're trying to do goes against the range design. You're free to 
try and work around the design in your own code to get done whatever you're 
trying to do, but we're not going to want that sort of thing in the standard 
library and are not going to encourage coding that way.

> > It has been proposed before that a function be added to Phobos which did
> > an
> > operation when iterating over an element, in which case that operation
> > would
> > go in popFront, and front would just return the wrapped front. That would
> > probably get you what you want and be more generally applicable than
> > cacheFront.
> 
> Are you referring to proposals for tap ? There were many proposed, so not
> sure which one you're mentioning. Or something else?

Probably. There were several names floating around. From what I recall, 
essentially what you'd get is that if you had something like

foreach(e; range.tap!tapFunc().map!mapFunc()) {...}

then tapFunc would be called for each range element as the range iterates 
prior to it being processed by map - probably when the element becomes the new 
front. I would think that you could get what you want with something like 
that. And if tap only worked for pre or post operations due to how it was put 
together, then it would probably be easy to create the opposite and have 
something like tapBefore and tapAfter where tapBefore's function was called 
before each element became front, and tapAfter's function was called after 
each element became front.

Though honestly, if I ever end up doing anything that doesn't quite fit into 
what the range-based functions in Phobos will already do for me, I'll just 
write my own, since it really isn't very hard and isn't a lot of code unless 
you trying to make it really generic (e.g. wrap any kind of range and take 
into account exactly what type of range you're trying to wrap and which of its 
functions can be forwarded). Simple forward ranges take very little code at 
all. So, I really don't find it to be a big deal to have to write my own ranges 
from time to time.

- Jonathan M Davis


More information about the Digitalmars-d mailing list