std.range.cacheFront proposal&working code: wraps a range to enforce front is called only once
Jonathan M Davis
jmdavisProg at gmx.com
Thu Oct 24 12:50:28 PDT 2013
On Thursday, October 24, 2013 12:14:27 Timothee Cour wrote:
> so far you've emphasized on the fact popFront should take care of all side
> effects and front should be logically pure and fast to compute, but you
> haven't suggested any alternative for what I'm trying to achieve.
>
> In what I propose it's generic (works in all cases) and simple (just add
> ".cacheFront" after a lambda with side effect):
>
> auto test(T)(T elements) if(isInputRange!T){
> return elements
> .map!( (a) {preaction(a); auto b=transform(a); postaction(a,b); return b;})
> .cacheFront
> .filter!foo; //or joiner or....
> }
>
> So, how do you achieve the above without using cacheFront, without creating
> a _custom_ range or writing a lot of code ?
> I don't see how using foreach is a good idea (ForEachType!=ElementType, it
> doesn't reuse phobos functionality and doesn't play well with phobos range
> functions)
If you don't want to do this with foreach, then creating a custom range is
exactly what you should be doing, and the logic for the pre and post
operations should go in popFront. 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. You can
do it if you want to, but that's not at all what they're designed for.
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.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list