On Wednesday, 4 September 2013 at 05:00:58 UTC, Jonathan M Davis wrote:
The main problem has to do with what you do when there's not enough room to write to it. Even checking the length isn't enough, because it's unknown ahead of time whether a particular code point (or string of characters if calling put with multiple characters) will fit - at least not without converting the character to UTF-8 first, which would incur additional cost, since presumably that would result in it being converted twice (once to check and once when
actually putting it).

Of course, it's a problem in general with output ranges that we haven't defined how to check whether put will succeed or what the normal procedure is when it's going to fail. My first suggestion for that would be to make it so that put returned whether it was successful or not, but it's something that probably needs to be discussed. However, with that problem solved, it may be
reasonable to make char[] an output range.

But until we sort out some of the remaining details of output ranges (most particularly how to deal with put failing, but there are probably other issues that I'm not thinking of at the moment), I don't think that it's a good idea to change how char[] is treated, since how all of that is sorted out could
have an effect on what we do with char[].

- Jonathan M Davis

Thanks for your reply. Yeah, the debate always boils back down to what "are arrays/input ranges output ranges, and what do we do when they are "full" (eg empty), and can we even detect it".

I think that given your answer, I will simply *not* make them output ranges, but I *will* make sure that making them as such is easy.

FYI (but it might need a little bit more work), I think I may be on to something. In my implementation, I defined a private function called "doPut". "doPut" is basically the last "atomic" operation in the "put" functionality.

Given a sink "s", and an element "e", it calls exactly the correct call of :
s.put(e);
s.front = e;
s(e);

It does *not* iterate over "e", if it is a range. It does *not* attempt to check [e], and it does *not* transcode "e". What this means is that basically, if you write "doPut(s, e)", then you are putting *exactly* the single element "e" into "s". It means the s is a "native" output range for "e": It doesn't need any help from "put".

From there, I defined the package trait "isNativeOutputRange(S, E)". If a pair S/E verify this "Native" variant of isOutputRange, then the user has the *guarantee* that "put(s, e)" will place *exactly* "e" into "s". This is particularly interesting for: 1. InputRanges: if the range is not empty, the *put* is guarateed to not overflow. 2. Certain format functions, such as "std.encoding.encode(C, S)(dchar c, S sink)", will transcode c into elements of type C, and place them in the output range S. Here, it is *vital* that no transcoding happen. My "doPut"/Native trait help guarantee this.

--------

Well, right now, it is only used as private implementation detail, but it works pretty good. It might be worth investigating in more details if we want this public?

Reply via email to