One way to deal with transient ranges & char[] buffers

Jakob Ovrum jakobovrum at gmail.com
Fri Aug 2 00:50:26 PDT 2013


On Friday, 2 August 2013 at 05:35:28 UTC, H. S. Teoh wrote:
> Recently, I discovered an interesting idiom for dealing with 
> transient
> ranges, esp. w.r.t. strings / char[]. Many places in D require 
> string,
> but sometimes what you have is char[] which can't be converted 
> to string
> except by .idup. But you don't want to .idup in generic code, 
> because if
> the input's already a string, then it's wasteful duplication.

Places in D that require `string` either do so because they need 
the immutable guarantee or they do so out of error (e.g. should 
have used a string of const characters instead). The latter can 
of course be worked around, but the only *solution* involves 
fixing the upstream code, so I'll assume we're discussing the 
former case.

We don't have any generic mechanism for deep copying ranges. The 
`save` primitive is often implemented by means of copying, but 
conceptually is doing something very different, so it cannot be 
applied here. So, I don't see how your idea translates to ranges 
in general (not completely sure if it was intended to).

Thus, let's tackle the case of arrays/slices in particular, of 
which strings are the most common example. There is a precedent 
in D to push to the decision to copy an array upwards in the 
code. When the operations at hand require the immutable 
guarantee, state it in the interface of the code, such as by 
asking for `string` on a function's parameter. That's why so many 
functions take `string` when they need the immutable guarantee, 
as opposed to `const(char)[]` or a template parameter, followed 
by a GC copy operation. This way, copies are not only minimized, 
but centralized more in user code where they are more visible, 
and the method of making the copy - remember, not all client code 
is fine with rampant GC use - is also pushed up. Also, copies are 
one thing, but what if the caller had a string but in a different 
encoding? Not only does an allocation have to be made, but 
decoding and encoding is also necessary; the details of how to 
handle this are also pushed up, with the same benefits. It's a 
pretty mainstream idiom and is often reiterated by members of the 
community, such as in Ali's talk at dconf.

Your proposed solution only shares one benefit with the solution 
described above - that if the direct caller had a `string` 
already (or a range of `string`s), nothing has to be done. It 
forfeits all the other benefits for convenience. It also has 
problems with template bloat, which can be fixed but at a 
syntactical cost.

Overall I think it reduces the genericity of algorithms by trying 
to handle input types it doesn't actually support, which can be a 
big problem for performance-critical code.


More information about the Digitalmars-d mailing list