www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Slightly modified array copies

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
Oct 10 2011