std.range pipelike interface, inverting OutputStreams?

ikod via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Aug 13 02:34:47 PDT 2016


On Saturday, 13 August 2016 at 02:15:55 UTC, cy wrote:
> I was trying to use std.regex, and it takes an output stream to 
> pump the result to, which is great, but I wanted to perform TWO 
> replacements, one with the output of the previous, with data 
> that might be a tricky size to cache redundantly.
>
> So, ideally when you do something like regexp replacing, you'd 
> have a function like:
> InputRange replaceThingy(InputRange source, someregex, 
> somereplacer);
>
> It doesn't do that, unfortunately, so I can't easily chain 
> replacements. But couldn't I do a thing like...
>
> InputRange pipe(void delegate(ref OutputRange)) { ? }
>
> and then just...
>   auto result = pipe((sink) => replaceAllInto(sink, data, 
> firstmatch, firstreplacer));
>   auto result2 = pipe((sink) => replaceAllInto(sink, result, 
> secondmatch, secondreplacer));
>   copy(result2,stdout);
>
> ... or something like that? Has that been done before? Can it 
> be done?
>
> I'm pretty sure any algorithm that takes an output stream can 
> be transformed into an algorithm that provides an input stream, 
> but I'm not sure if I'd be reinventing the wheel here, or if my 
> assumptions are seriously off.
>
> Hoping to avoid weird stuff like context switches... eh.

Looks like you can't just because std.regex replace* functions 
accept only someString as input.

But you can write something like this (sorry for dirty code):
import std.regex;
import std.stdio;

class ReplacePipe {
     private {
         Regex!char   _re;
         string       _format;
         string       _input;
         ReplacePipe  _next;
     }
     this(string input, string r, string f) {
         _re = regex(r);
         _format = f;
         _input = input;
     }
     this(ReplacePipe next, string r, string f) {
         _re = regex(r);
         _format = f;
         _next = next;
     }
     string go(string i) {
         return replaceAll(i, _re, _format);
     }
     string go() {
         if ( _next ) {
             auto s = _next.go();
             return replaceAll(s, _re, _format);;
         }
         return go(_input);
     }
}
ReplacePipe replacePipe(string data, string r, string c) {
     return new ReplacePipe(data, r, c);
}
ReplacePipe replacePipe(ReplacePipe output, string r, string c) {
     return new ReplacePipe(output, r, c);
}
void main() {
     string input = "1 2, 3 4";
     auto a = input.replacePipe(r" ", "+").replacePipe(r"\+", 
".").go();
     assert(a=="1.2,.3.4");
}



More information about the Digitalmars-d-learn mailing list