Transient ranges

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Mon Jun 13 06:59:06 PDT 2016


On 6/12/16 4:46 AM, Dicebot wrote:
> On Friday, 3 June 2016 at 12:03:26 UTC, Steven Schveighoffer wrote:

>> Yes, I can see good reason why you would want this. Hm... a set of
>> adapters which reduce a range to its lesser API would be useful here:
>>
>> array.asInput.map
>>
>> But an expectation for map should be that you want it to be exactly
>> the same as the original, but with a transformation applied to each
>> fetch of an element. I think it needs to provide random access if
>> random access is provided to it.
>
> That is matter of design philosophy. For me such basic library
> primitives warrant C++ attitude of "don't pay for what you don't ask
> for" - and everything else, including actual feature completeness, is of
> negligible importance compared to that. If keeping random access for map
> requires either caching or multiple evaluations of predicate, I want it
> to be banned by default and enabled explicitly (not sure what could be
> good API for that though).

So what it seems like you want is somerange.map(...).front to evaluate 
the lambda only once, without caching. This doesn't fit into the 
definition of ranges, which require the ability to access the same front 
more than once.

What you really want is a new kind of construct. It's not a range.

Given that front must be accessible more than once, map has to make a 
choice, caching or reevaluating. Not doing one of those two things is 
not an option for ranges.

Note that this has nothing to do with random access.

> Phobos indeed doesn't seem to make such priorities right now and that is
> one of reasons I am growing increasingly unhappy with it.

It's not so much that Phobos attempts to give you kitchen sink support 
at all costs, it's that if the sink being passed in has all the faucets, 
it'll forward them for free if possible.

>>>> Then it's not a bug? It's going to work just fine how you specified
>>>> it. I just don't consider it a valid "range" for general purposes.
>>>>
>>>> You can do this if you want caching:
>>>>
>>>> only(0).map!(x => uniform(0, 10)).cache
>>>
>>> Good advice. Don't want bugs with non-stable results and accidental
>>> double I/O in your long idiomatic range pipeline? Just put "cache" calls
>>> everywhere just to be safe, defensive programming for the win!
>>
>> Strawman, not what I said.
>
> But that is what your answer meant in context of my original question :)
> My complaint was about existing semantics are being error-prone and hard
> to spot - you proposed it by adding more _manual_ fixup, which kills the
> whole point.

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.


More information about the Digitalmars-d mailing list