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