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 10:57:43 PDT 2013
On Thursday, October 24, 2013 09:56:24 Timothee Cour wrote:
> that changes semantics: what if you want to do some actions before and
> after accessing the front element. You'd have to do quite a big of
> gymnastics to do that in popFront:
> eg:
> elements.map!( (a) {preaction(a); auto b=transform(a); postaction(a,b);
> return b;}) . filter/sort/map/etc
>
> With what I proposed, it is possible, and it guarantees the lambda will be
> called once at most per element.
And why are you doing these preactions or postactions inside of something like
map? IMHO, doing anything that doesn't involve creating the new front should
be done outside of map.
Now, that being said, I'd argue that map should probably be changed so that it
calls its function on popFront rather than front (though that has the downside
of requiring that it then hold the current value, which it doesn't currently
have to do), but regardless, you're using map for something other than what it
was designed to do. It makes no guarantees of how many times the function you
pass it will be called, so while it should minimize the number of calls for
efficiency's sake, it's just wrong to rely on it being called only once. There
is _nothing_ about ranges which makes such a guarantee (and map follows the
standard range semantics without providing any additional guarantees).
Logically, there is no difference between front as member function or as a
member variable, and it should act like a member variable - which means no
side effects. At most, it should be calculating the current value of front, but
ideally, that value would be stored in order to avoid hidden costs when front
ends up being called multiple times between calls to popFront.
You're obviously free to create wrappers around your ranges which do things
like cache the value of front and don't call front on the wrapped range more
than once per call to popFront, but when you require such a wrapper, you're
violating the basic concept of how front is supposed to work per the standard
range semantics. front is supposed to either be a member variable or to
emulate the semantics of one, and than means no side effects. IMHO, if what
you're doing requires side effects in front, then you really need to rethink
how you're using ranges.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list