Why is there no lazy `format`?
burt
invalid_email_address at cab.abc
Tue Oct 20 18:24:01 UTC 2020
On Tuesday, 20 October 2020 at 18:03:32 UTC, H. S. Teoh wrote:
> [...]
>
> Yeah, I think std.format's design isn't really conducive to
> lazy access. Also, the way the OP wrote the example code isn't
> really consistent, because it appears to be returning segments
> of the formatted string rather than characters in the string,
> i.e., it behaves like `string[]` rather than `string`, which
> isn't how std.format is designed to work.
Well, the idea was that you could call `join()` or `flatten()` or
whatever it is called to turn it into an input range of chars.
But it could also do that directly.
I understand now why returning an input range could be
problematic though.
> [...]
> What *would* be nice, is a standard library construct for
> inverting an output range into an input range. Fibers is one
> way of doing this. Basically, the pipeline up to the output
> range will run in its own fiber, and initially it's
> backgrounded. As data is requested from the input range end of
> the interface, it will context-switch to the output range fiber
> and generate data which gets saved into a buffer. At some point
> calling Fiber.yield(); then the input range end will start
> spooling the generated data to the caller. Once the buffered
> data is exhausted, it context-switches to the output range
> fiber again, etc..
>
> Note that this does not alleviate the need for buffering, and
> it's not 100% lazy; what it primarily does is to give a nice
> input range interface for stuff written into an output range.
> I don't expect it will do very well performance-wise either,
> unless the data generators are designed to cooperate with the
> inverter -- but in that case, they would have been written to
> return an input range instead of requiring an output range in
> the first place. So this construct is really more for
> convenience than anything.
Interesting idea. Although maybe it doesn't even have to use
fibers to work, if you're willing to give up the laziness part:
```
/*ref*/ O pipeRange(alias fn, O, T...)(/*ref*/ O output, T args)
if (isInputRange!O && isOutputRange!O)
{
fn(output, args);
return output;
}
auto thing = appender!string()
.pipeRange!formattedWrite("%d plus %d is %d", 1, 2, 3)
.map!toUpperCase()
.array();
```
Or something like that.
More information about the Digitalmars-d
mailing list