const?? When and why? This is ugly!
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Sat Mar 7 15:19:50 PST 2009
Burton Radons wrote:
> Walter Bright Wrote:
>
>> Burton Radons wrote:
>>> That's what we said about strings in 1.0. You modify it, you copy
>>> it, or you tell the user. The gentleman's agreement worked
>>> perfectly and that came without a mess of keywords, without
>>> implicit or explicit restrictions on behaviour, without having to
>>> condition templates.
>> The one flaw in it was the behavior I consistently saw of "I'm
>> copying the string just to be sure I own it and nobody else changes
>> it." D was meant for copy-on-write, which means copy the string
>> *only* if you change it. No defensive copying. No "just in case"
>> copying. The gentleman's agreement failed as far as I could tell.
>>
>> With immutable strings, the gentleman's agreement is enforced.
>
> Am I going to become a broken record on this? Because "invariant
> (char) []" is the string type, data that is going to be mutable will
> always find its way into that type in order to deal with an API which
> WILL use string as its arguments, not writing out "const (char) []".
> It gives me no information about the future of the object while
> removing the apparent need for the gentleman's agreement. Therefore I
> have no way of knowing what the actual pedigree of this string I've
> been given has. It may be invariant, it may be mutable.
>
> I want this to be addressed directly. Exactly how am I wrong on this
> point? Is it not conceivable that mutable data gets casted to
> invariant in this case?
It is conceivable by means of a cast. I've explained that casts can
break any of D's guarantees, so there is nothing new that you can
masquerade a mutable string into an immutable one. If there was a means
to implicitly convert a mutable string into an immutable one, you'd have
a case. But it either looks like you're not understanding something, or
are using a double standard when it comes about casting as applied to
immutability in particular.
There is one point where we are forced to doing something gauche:
assumeUnique. We could have avoided that by introducing a "unique"
notion, but we thought we'd simplify the language by not doing so. So
far the uses of assumeUnique seem to be idiomatic and contained enough
to not be a threat, so it seems to have been a passable engineering
decision.
To recap, if an API takes a string and all you have a char[], DO NOT
CAST IT. Call .idup - better safe than sorry. The API may evolve and
store a reference for later. Case in point: the up-and-coming
std.stdio.File constructor initially was:
this(in char[] filename);
Later on I decided to save the filename for error message reporting and
the such. Now I had two choices:
(1) Leave the signature unchanged and issue an idup:
this.filename = to!string(filename); // issues an idup
(2) Change the signature to
this(string filename);
Now all client code that DID pass a string in the first place (the vast
majority) was safe _and_ efficient. The minority of client code was that
that had a char[] or a const(char)[] at hand. That code did not compile,
so it had to insert a to!string on the caller side.
As has been copiously shown in other languages, the need for
character-level mutable string is rather rare. So most of the time you
will not traffic in char[], but instead you'll have a immutable(char)[]
to start with. This further erodes the legitimacy of your concern.
I have no idea how to make this any more clearer. I explained it so many
times and in so many ways, even I understood it :o).
Andrei
More information about the Digitalmars-d
mailing list