Implicit conversion of unique objects to mutable and immutable
Jonathan M Davis
jmdavisProg at gmx.com
Tue Jun 21 16:02:43 PDT 2011
On 2011-06-21 15:25, Ali Çehreli wrote:
> (Note: I have a feeling that this must be related to the old 'unique'
> discussions, which I had somehow managed to stay out of. If so, I
> apologize for repeating an old story.)
>
> It is most useful for a function to return the most mutable type unless
> there is good reason not to. Do you agree?
No. In a lot of cases, what you generally want is immutable, not mutable. In
particular, if you're talking about strings, we favor string, wstring, and
dstring over char[], wchar[], or dchar[] unless you actually need to alter the
string. The default is to use immutable. You save memory, it works well with
threading, and it increases the opportunites for optimization. There's
generally little benefit to having strings be mutable (which is why string is
an alias to immutable(char)[], not char[]). char[], wchar, and dchar[] are
there if you need them (and obviously sometimes you do), but in general,
immutable is preferred, because it's generally more efficient.
Now, outside of strings, it varies a lot more as to whether immutable, const
or mutable is preferred, since there are plenty of other types which get
mutated all of the time. But there are still huge advantages to const and
immutable in the general case, so there are plenty of situations where
defaulting to the least mutable type possible is the best solution. It does
vary depending on the situation, however.
> foo() makes a fresh result and
> returns it:
>
> char[] foo()
> {
> char[] result;
> return result;
> }
>
> The caller can get the result as a char[] and modify it:
>
> char[] result = foo();
> result[0] = 'A'; // assume a valid element
>
> But what if the caller wants to treat the returned value as immutable:
>
> string result = foo();
>
> That's currently a compilation error: "Error: cannot implicitly convert
> expression (foo()) of type char[] to string"
>
> When it makes sense, we have std.exception.assumeUnique() for the caller
> to use:
>
> import std.exception;
>
> // ...
>
> char[] result = foo();
> string immutable_result = assumeUnique(result);
>
> But that's the wrong thing to do, as foo() may be changed in the future
> to return a non-unique result. I think the language should have the
> 'unique' qualifier so that foo() could use it on the return type:
>
> unique char[] foo()
> {
> // ...
> }
>
> and the unique objects could be converted to immutable or mutable
> implicitly:
>
> string immutable_result = foo(); // fine
> char[] mutable_result = foo(); // fine too
>
> Is this whole thing the same as that old 'unique' discussion? :)
It relates - particularly if foo is strongly pure, because then it's
guaranteed that the result of foo is either unique or it's immutable and
therefore it doesn't matter.
> But anyway... How do you solve the problem of deciding the return type of
> such functions?
Generally, you pick. Normally, we favor string over char[]. Immutability is
generally favored over mutability when it comes to strings. The major elements
which affect what a string function returns though are the function's
arguments and what the function actually does. If the function is going to
allocate a string, then it's generally going to return immutable. But if it's
going to return a slice, then its return type is going to depend on what you
passed in (in which case, the function is templated or it just uses const).
Of course, you can always templatize the function and have it default to
whatever string type you want to be the default, and then pass the type that
you want if you want a different one.
string s = foo!string();
char[] t = foo!(char[])();
But I don't think that that's particularly normal thing to do. Phobos
generally either just uses string, or the type of string that it returns
depends on its arguments (generally because it's going to return a slice
rather than a new string).
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list