Idiomatic way to write a range that tracks how much it consumes

Jon Degenhardt jond at noreply.com
Mon Apr 27 06:08:29 UTC 2020


On Monday, 27 April 2020 at 05:06:21 UTC, anon wrote:
> To implement your option A you could simply use 
> std.range.enumerate.
>
> Would something like this work?
>
> import std.algorithm.iteration : map;
> import std.algorithm.searching : until;
> import std.range : tee;
>
> size_t bytesConsumed;
> auto result = input.map!(a => a.yourTransformation )
>                    .until!(stringTerminator)
>                    .tee!(a => bytesConsumed++);
> // bytesConsumed is automatically updated as result is consumed

That's interesting. Wouldn't work quite like, but something 
similar would, but I don't think it quite achieves what I want.

One thing that's missing is that the initial input is simply a 
string, there's nothing to map over at that point. There is 
however a transformation step that transforms the string into a 
sequence of slices. Then there's a transformation on those 
slices. That would be a step prior to the 'map' step. Also, in my 
case 'map' cannot be used, because each slice may produce 
multiple outputs.

The specifics are minor details, not really so important. The 
implementation can take a form along the lines described. 
However, structuring like this exposes the details of these steps 
to all callers. That is, all callers would have to write the code 
above.

My goal is encapsulate the steps into a single range all callers 
can use. That is, encapsulate something like the steps you have 
above in a standalone range that takes the input string as an 
argument, produces all the output elements, and preserves the 
bytesConsumed in a way the caller can access it.


More information about the Digitalmars-d-learn mailing list