On Friday, 18 July 2014 at 00:08:17 UTC, H. S. Teoh via Digitalmars-d wrote:
On Thu, Jul 17, 2014 at 06:32:58PM +0000, Dicebot via Digitalmars-d wrote:
On Thursday, 17 July 2014 at 18:22:11 UTC, H. S. Teoh via Digitalmars-d
wrote:
>Actually, I've realized that output ranges are really only >useful >when you want to store the final result. For data in >mid-processing, >you really want to be exporting an input (or higher) range >interface
>instead, because functions that take output ranges are not
>composable.  And for storing final results, you just use
>std.algorithm.copy, so there's really no need for many >functions to
>take an output range at all.

Plain algorithm ranges rarely need to allocate at all so those are somewhat irrelevant to the topic. What I am speaking about are variety
of utility functions like this:

S detab(S)(S s, size_t tabSize = 8)
    if (isSomeString!S)

this allocates result string. Proper alternative:

S detab(S)(ref S output, size_t tabSize = 8)
    if (isSomeString!S);

plus

void detab(S, OR)(OR output, size_t tab_Size = 8)
    if (   isSomeString!S
        && isSomeString!(ElementType!OR)
       )

I think you're missing the input parameter. :)

        void detab(S, OR)(S s, OR output, size_t tabSize = 8) { ... }

I argue that you can just turn it into this:

        auto withoutTabs(S)(S s, size_t tabSize = 8)
        {
                static struct Result {
                        ... // implementation here
                }
                static assert(isInputRange!Result);
                return Result(s, tabSize);
        }

        auto myInput = "...";
        auto detabbedInput = myInput.withoutTabs.array;

        // Or:
        MyOutputRange sink;     // allocate using whatever scheme you want
        myInput.withoutTabs.copy(sink);

The algorithm itself doesn't need to know where the result will end up -- sink could be stdout, in which case no allocation is needed at all.

Yes this looks better.

Reply via email to