Slightly modified array copies

bearophile bearophileHUGS at lycos.com
Mon Oct 10 18:07:18 PDT 2011


New features (like transitive immutability) give birth to new appetites, like the following one, that weren't present before.

Sometimes I have an array of immutable things, like a string (and maybe I can't use an array of chars because I will have to use the strings as associative array keys), and I have to generate slightly modified arrays.

I need to keep both the original and the modified version, so in theory there is no need to go into undefined behaviour converting doing a const->mutable operation.


Here is a way to do it now, this is save and clean and easy, but it contains an unnecessary copy. This is acceptable often, but it's not acceptable if similar code is in critical path that needs to be fast:

char[] aux = text.dup; // not nothrow still
aux[i] = 'A';
aux[j] = 'B';
text = aux.idup;


This is a bit better, there is only a single copy. In practice this is rather safe code (assumeUnique sets aux to empty string), but D type system doesn't help you a lot here:

char[] aux = text.dup; // not nothrow still
aux[i] = 'A';
aux[j] = 'B';
text = assumeUnique(aux);


In the latest versions of D this is an alternative solution that avoids punching any kind of hole in the D type system:


static string temp_(immutable string d, size_t i1, char c1,
                    size_t i2, char c2) pure {
    char[] aux = d.dup; // not nothrow
    aux[i1] = c1;
    aux[i2] = c2;
    return aux;
}
data = temp_(data, i, 'A', j, 'B');


But that't long, and slow.


Note that today you can't write this, despite the semantics is similar:


static void temp_(ref string d, size_t i1, char c1,
                  size_t i2, char c2) pure {
    char[] aux = d.dup; // not nothrow
    aux[i1] = c1;
    aux[i2] = c2;
    d = aux;
}
temp_(data, i, 'A', j, 'B');


In languages designed for mostly immutable data structures (like Clojure, Haskell) the immutable data structures offer ways to safely (and efficiently!) create slightly modified versions of them. This is a common need.

This is a possible syntax to create a slightly modified copy of an array of immutables, keeping full type system safety (time ago I have found a similar syntax in another language, maybe Ada, I don't remember well):

text = text.idup(i: 'A', j: 'B');

-------------------------

Partially related, are you able to tell me if this enhancement request of mine is valid?
http://d.puremagic.com/issues/show_bug.cgi?id=6783

That enhancement request asks for code like this too to be accepted, but I am not sure it is legit:


immutable(int[]) foo(in int[] x) pure {
    return new int[1];
}
void main() {}


Bye,
bearophile


More information about the Digitalmars-d mailing list