Func Param Confusion - in/out/inout/ref/const/immutable

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Feb 22 11:35:33 PST 2013


On Fri, Feb 22, 2013 at 08:19:49PM +0100, Zane wrote:
> When is it appropriate to use in, out, inout, ref, immutable, and
> const in function parameters?

Don't use 'in', because it doesn't mean what it seems to mean, and it's
not correctly implemented at the moment.


> I read the documentation and understand the basics behind them, but
> I'm a little confused, for example, why someone would want to use
> 'out' instead of 'ref', why 'in' instead of 'const', or why
> 'immutable' instead of 'const'?

The difference between 'ref' and 'out' is that 'out' will
default-initialize the parameter, so the function will not see whatever
original value is in the variable that you pass in, whereas 'ref' is for
passing in an initial value and (possibly) receiving a new value
afterwards.

'immutable' is for when you want to be 100% sure that whatever value it
is cannot be changed by a third party. With 'const', it just means the
function can't modify the value, but somebody else may have a writable
alias to the same data. You want to use 'immutable' when your function
needs to assume that no external agents can change the data (e.g., if
the function puts the data in some kind of persistent data structure
that depends on the value not being changed from outside unexpectedly).


> If 'inout' is used as a wildcard, allowing for any of several storage
> classes, why is it needed at all (wouldn't 'ref' work?).

What 'inout' means is that the parameter is either mutable or const, and
that whatever this qualifier is, the return value will acquire the same
qualifier. For example:

	inout(int) func(inout(int[]) values, int idx)
	{
		return values[idx];
	}

The compiler actually treats it as two different functions:

	int func(int[] values, int idx)

and:

	const(int) func(const(int[]) values, int idx)

This is because int and const(int) are different types, so you couldn't
write the same function for it even if the function body is identical.
In order to alleviate the tedium (and bug-proneness) of copy-n-pasting
the function body, 'inout' was introduced, so that by writing
inout(int), you can write the function once, and it can be used for
both const(int[]) and int[].

Within the function body, an inout value is treated exactly like const,
that is, the function is not allowed to modify it. This is to guarantee
that the function doesn't do something fishy to modify the data, since
otherwise it would be wrong to allow passing const(int[]) to the same
function, which means it cannot be an inout function.


> The more I think I get it, the more I end up getting confused. Am I
> thinking about this too hard? FYI: I come from primarily a C/Java/PHP
> background, so these concepts are relatively new to me - it feels
> excessive, though I am willing to learn.

It may help to understand that D's const is different from C/C++'s
const. D's const comes with compiler guarantees; it means *physical*
const, not logical const. That is, the physical binary representation of
the data is not modifiable; so something like a class that caches
function results will not be allowed to be const. This diagram will be
most helpful to understand how it all works:

	      const
	     /     \
	mutable    immutable

What this means is that you can implicitly convert mutable or immutable
into const, but you cannot go the other way, and you cannot convert
between mutable and immutable (with the exception of certain safe
operations, like making a copy of immutable(int), which is allowed
because it's a POD that actually gets copied into a new physical
location, so assigning immutable(int) to int is allowed. But in general,
immutable(X) cannot be assigned to X).

Generally, function parameters don't need to be immutable (except for
special cases); usually you'd use const because then you can pass in
either mutable (i.e. unqualified) or immutable, and it will work
correctly.

Hope this helps.


T

-- 
He who laughs last thinks slowest.


More information about the Digitalmars-d-learn mailing list