On const and inout (was Re: Logical const)
Bruno Medeiros
brunodomedeiros+spam at com.gmail
Fri Dec 3 09:41:33 PST 2010
On 02/12/2010 09:18, Don wrote:
> Walter Bright wrote:
>> spir wrote:
>>> What would be the consequences if D had no const, only immutable
>>> (that, IIUC, removes the latter non-guarantee)?
>>
>> You'd have to write most every function twice, once to take immutable
>> args and again for mutable ones.
>
> Doesn't 'inout' do almost the same thing?
> The only difference I can see between const and inout, is that inout
> tells which parameters could be aliased with the return value.
Yes, that is more or less it, although it may not the best way to think
about it.
I've come to realize an interesting parallel between inout and Java
wildcards. In fact, that might give inspiration for another way to
explain inout and const. Let's go back a little, to think about const
itself.
Ask yourselves this, does it makes sense to *instantiate* data typed as
const, such as this:
auto blah = new const(int[4]);
?
The answer is no (even though the compiler allows it). The resulting
data would effectively be the same as immutable, so you might as well
instantiate it as immutable. The key thing here is that const(int), and
any other const(T), is actually kinda like an abstract type. It tells
you some of the things you can do with the data, but the data itself
must be of a concrete type, which is mutable or immutable, but not
const. It is entirely accurate to think of const(T) as some T that can
be mutable or immutable, but one don't know which, so one can only work
on the lowest common assumptions. So const is like a wildcard.
Why is this interesting? Because it helps us understand what inout does.
(if some people have trouble understanding and/or explaining const, then
inout will be much worse). inout is based on const, it also says "I
don't know if this data is mutable or not". However, it adds the
guarantee/restriction that all data typed as inout in the function
parameters and return type actually has the same *concrete* type, with
regards to immutability. So if you have this function:
inout(int)[] func(inout(int)[] arr, int x, int y) {
return arr[x .. y];
}
You are specifying: I don't know what arr's actual/real/runtime
immutability is (so I'll treat is an unknown), but I guarantee that the
actual/real/runtime immutability of the return type will be that same as
that of arr's.
This pretty much the same conceptually as creating a binding of a
wildcard type in Java (I'm not sure these are the correct terms). Java's
wildcard support is much more... err.. of a generic solution (I mean
generic as in http://www.answers.com/generic, not as in related to
generics). For example, in Java you can specify a function signature
such as this:
public static <T> T get(T obj) { //...
Which guarantees that the static return type is the same as the static
type of the argument. So for example this will compile:
String foo = get(new String());
Number foo = get(new Integer());
but this will not:
Number foo = get(new String());
Conceptually this is pretty much the same as with inout in D, where
inout is only able to bind to one type modifier, and it does so
anonymously.
Also D's support for this is only with regards to immutability,
otherwise D is not able to define _one_ function with a
signature/contract like the above.
--
Bruno Medeiros - Software Engineer
More information about the Digitalmars-d
mailing list