On Monday, 13 June 2016 at 13:59:06 UTC, Steven Schveighoffer
wrote:
No, it's not. My advice is to understand the limitations and
expectations of the range wrappers you are using (i.e. read the
docs [1]). If you need caching for your purposes, then do that
by plopping cache at the end of your use case. The user must
have to understand that providing a mapping function that does
random things (or even varying things on each call) is going to
result in unexpected behavior. The compiler cannot foresee the
purpose of your lambda code.
You just said only pay for what you ask for. I don't want to
pay for caching for map if I don't need it. I'd be pissed if
map cached for something like map!(x => x * 2). If you want
caching, then ask for it.
There was a talk by Herb Sutter on atomic operations on various
platforms. His general rule was, as long as you don't write
race conditions, and use only provided atomics, your code will
do what you think. We can apply a similar rule here: as long as
you write a lambda which for a given input will provide the
same result, map will do what you expect. When you try odd
things like your random call, we don't guarantee things will
work like you expect. You may utilize the knowledge of how map
works, and how the things that are using the map work to write
something clever that breaks the rules. But no guarantees.
-Steve
[1] I admit, the map docs aren't explicit about this, and
should be.
I see three levels of function used with map:
pure: everything is as expected, consider caching if expensive.
idempotent side-effects: remember map is lazy and you'll be ok.
non-idempotent side-effects: probably not what you want.