to compose or hack?

Steven Schveighoffer schveiguy at gmail.com
Wed Jul 7 13:30:28 UTC 2021


On 7/7/21 5:54 AM, rassoc wrote:
> On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer wrote:
>> So I have this situation where I need to split a string, then where 
>> the splits are, insert a string to go between the elements making a 
>> new range, all without allocating (hopefully).
>>
> 
> Without considering the more general case, isn't that just splitter-joiner?

No, splitter-joiner would make a range of characters, I want a range of 
strings.

> ```d
> import std;
> 
> auto foo(string s, string sp, string j) @nogc {
>      return s.splitter(sp).joiner(j);
> }
> 
> void main() {
>      foo("ab,cd,ef,gh", ",", "##").writeln; // => ab##cd##ef##gh
> }
> ```

Using your example, the correct result should be `["ab", "##", "cd", 
"##", "ef", "##", "gh"]`

> 
> Interesting! Tried it myself, shame that this doesn't quite work:
> 
> ```d
> import std;
> 
> auto foo(R)(string s, string sp, R r) @nogc {
>      return s.splitter(sp).zip(r)
>              .map!(a => a.expand.only)
>              .joiner.dropBackOne.joiner; // not bidirectional
> }
> 
> void main() {
>      foo("ab,cd,ef,gh", ",", ["##", "**"].cycle).writeln;
> }
> ```

ooh, I like the zip/expand/only trick! I got this to work, and lol, I 
don't think I'd ever use this:

```d
auto interleave(R, U)(R src, U middles) if (isInputRange!R && is(U == 
ElementType!R))
{
     return zip(StoppingPolicy.shortest, src, middles.repeat)
           .map!(e => only(e.expand))
           .joiner
           .slide(2)
           .frontTransversal;
}
```

Ironically, I think it would still run the splitting algorithm 2x, 
because `slide` has to store 2 copies of the source range. And it's not 
nogc either. Hm... I bet `dropBackOne` might actually be able to work on 
a forward range if it cached one element? But that might be iffy.

-Steve


More information about the Digitalmars-d-learn mailing list