## digitalmars.D - Invariant Question (yes, another one)

• Janice Caron (6/6) Nov 15 2007 I got this error...
• Xinok (5/14) Nov 15 2007 Const is the read-only type, meaning that the data COULD change
• Janice Caron (5/10) Nov 15 2007 I don't follow that reasoning. Please explain in more detail.
• Matti Niemenmaa (8/21) Nov 15 2007 If I understood correctly:
• Regan Heath (25/38) Nov 15 2007 Yep. You know all this already but this might be of interest to others....
• Janice Caron (3/4) Nov 15 2007 Thank you. That makes absolutely perfect sense!
• Steven Schveighoffer (11/17) Nov 15 2007 Your first data type is an AA with invariant strings as keys and values....
• Janice Caron (11/15) Nov 15 2007 Yes, you're right.
• Regan Heath (12/32) Nov 15 2007 void main()
• Steven Schveighoffer (8/23) Nov 15 2007 Yes, this makes sense, because you then wouldn't be able to change any
• Reiner Pope (5/25) Nov 15 2007 I think it's just the odd behaviour that invariant(char[])[] is actually...
"Janice Caron" <caron800 googlemail.com> writes:
```I got this error...

Error: cannot implicitly convert expression (aa) of type
invariant(char)[][invariant(char)[]] to const(char)[][const(char)[]]

Why not?

Since invariant(char)[] can implicitly convert to const(char)[], I
just don't see a problem with this.
```
Nov 15 2007
Xinok <xnknet gmail.com> writes:
```Const is the read-only type, meaning that the data COULD change
unexpectedly. However, invariant means the data is guaranteed never to
change. You can't guarantee const data is never going to change, which
is why it gives you an error.

Janice Caron wrote:
I got this error...

Error: cannot implicitly convert expression (aa) of type
invariant(char)[][invariant(char)[]] to const(char)[][const(char)[]]

Why not?

Since invariant(char)[] can implicitly convert to const(char)[], I
just don't see a problem with this.

```
Nov 15 2007
"Janice Caron" <caron800 googlemail.com> writes:
```On 11/15/07, Xinok <xnknet gmail.com> wrote:
Const is the read-only type, meaning that the data COULD change
unexpectedly. However, invariant means the data is guaranteed never to
change. You can't guarantee const data is never going to change,

I know that. You're stating the obvious.

which
is why it gives you an error.

I don't follow that reasoning. Please explain in more detail.
invariant(char)[] can always be implicitly cast to const(char)[] ...
and that's exactly what I'm trying to do.
```
Nov 15 2007
Matti Niemenmaa <see_signature for.real.address> writes:
```Janice Caron wrote:
On 11/15/07, Xinok <xnknet gmail.com> wrote:
Const is the read-only type, meaning that the data COULD change
unexpectedly. However, invariant means the data is guaranteed never to
change. You can't guarantee const data is never going to change,

I know that. You're stating the obvious.

which
is why it gives you an error.

I don't follow that reasoning. Please explain in more detail.
invariant(char)[] can always be implicitly cast to const(char)[] ...
and that's exactly what I'm trying to do.

If I understood correctly:

An invariant variable cannot change, period. If you cast an invariant variable
to const, and then change it through the const variable (this bit seems dubious
to me), the invariant variable has changed. But this isn't permissible. Hence,
you can't cast invariant to const.

--
E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
```
Nov 15 2007
"Janice Caron" <caron800 googlemail.com> writes:
```On 11/15/07, Matti Niemenmaa <see_signature for.real.address> wrote:
If I understood correctly:

An invariant variable cannot change, period. If you cast an invariant variable
to const, and then change it through the const variable (this bit seems dubious
to me), the invariant variable has changed. But this isn't permissible. Hence,
you can't cast invariant to const.

Ah! I'm afraid you're wrong.

You /can/ cast from invariant to const - and in fact, this kind of
cast is IMPLICIT. For example:

invariant(char)[] s = "hello";
const(char)[] t = s; /* OK - compiles fine */

What you cannot do is "change it through the const variable". That's
illegal. Absolutely illegal. In the docs, Walter says it is
"undefined". Short version - never do this!

char[] u = cast(char[]) s; // BAD!

(The slightly longer version is you actually can do that if you
really, really know what you're doing, and you've got mutex locks and
such to absolutely guarantee well-defined behaviour, but it's not for
the faint-hearted).
```
Nov 15 2007
Regan Heath <regan netmail.co.nz> writes:
```Janice Caron wrote:
On 11/15/07, Xinok <xnknet gmail.com> wrote:
Const is the read-only type, meaning that the data COULD change
unexpectedly. However, invariant means the data is guaranteed never to
change. You can't guarantee const data is never going to change,

I know that. You're stating the obvious.

which
is why it gives you an error.

I don't follow that reasoning. Please explain in more detail.
invariant(char)[] can always be implicitly cast to const(char)[] ...
and that's exactly what I'm trying to do.

Yep.  You know all this already but this might be of interest to others...

http://www.digitalmars.com/d/final-const-invariant.html

"Implicit Conversions

Mutable and invariant types can be implicitly converted to const.
Mutable types cannot be implicitly converted to invariant, and vice versa. "

It makes sense to allow a read-only view (const) of data which cannot
change (invariant), just as it makes sense to allow a read-only view of
data which can.  In fact it's irrelevant whether the data can or cannot
change because all const promises is that changes wont occur via the
const reference itself.

Returning to the problem at hand... Steven makes a good point.  The AA
itself is not invariant, or const.  So, suppose you have:

void main()
{
char[] bob = "bob".dup;
char[] fred = "fred".dup;

invariant(char)[][invariant(char)[]] iaa;
const(char)[][const(char)[]] caa;

iaa["hello"] = "world";
caa = iaa;  //pretend this is allowed

caa[bob] = fred;
}

Now iaa contains bob and fred which are not invariant.

Regan
```
Nov 15 2007
"Janice Caron" <caron800 googlemail.com> writes:
```On 11/15/07, Regan Heath <regan netmail.co.nz> wrote:
Now iaa contains bob and fred which are not invariant.

Thank you. That makes absolutely perfect sense!

Of course, now I'm going to have to think a bit harder about my code! :-)
```
Nov 15 2007
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```"Janice Caron" wrote
I got this error...

Error: cannot implicitly convert expression (aa) of type
invariant(char)[][invariant(char)[]] to const(char)[][const(char)[]]

Why not?

Since invariant(char)[] can implicitly convert to const(char)[], I
just don't see a problem with this.

Your first data type is an AA with invariant strings as keys and values.
HOWEVER, the AA itself is not invariant.  Suppose after you converted to an
AA with const strings as keys and values, you replaced one of the values
with a mutable string cast into a const string.   I think what you might
want is:

const(const(char)[][const(char)[]])

This guarantees that the data will not be changed no matter what.

But I'm not sure this will work either.  It should, but I don't know if the
compiler is smart enough to figure this out?

-Steve
```
Nov 15 2007
"Janice Caron" <caron800 googlemail.com> writes:
```On 11/15/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
Your first data type is an AA with invariant strings as keys and values.
HOWEVER, the AA itself is not invariant.  Suppose after you converted to an
AA with const strings as keys and values, you replaced one of the values
with a mutable string cast into a const string.

Yes, you're right.

invariant(char)[][] won't implicitly convert to const(char)[][]
either, for the same reason.
But...
invariant(char[])[] will implicitly conver to const(char[])[]

But here's the odd thing...

invariant(char[])[] will implicitly conver to const(char[])[]
but
invariant(char[])[int] won't implicitly convert to const(char[])[int]

The only difference is the int in the square brackets.
```
Nov 15 2007
Regan Heath <regan netmail.co.nz> writes:
```Janice Caron wrote:
On 11/15/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
Your first data type is an AA with invariant strings as keys and values.
HOWEVER, the AA itself is not invariant.  Suppose after you converted to an
AA with const strings as keys and values, you replaced one of the values
with a mutable string cast into a const string.

Yes, you're right.

invariant(char)[][] won't implicitly convert to const(char)[][]
either, for the same reason.
But...
invariant(char[])[] will implicitly conver to const(char[])[]

But here's the odd thing...

invariant(char[])[] will implicitly conver to const(char[])[]
but
invariant(char[])[int] won't implicitly convert to const(char[])[int]

The only difference is the int in the square brackets.

void main()
{
char[] fred = "fred".dup;

invariant(char)[][int] iaa;
const(char)[][int] caa;

iaa[1] = "world";
caa = iaa;  //pretend this is allowed

caa[2] = fred;
}

Using the same reasoning :)

Regan
```
Nov 15 2007
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```"Janice Caron" wrote
On 11/15/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
Your first data type is an AA with invariant strings as keys and values.
HOWEVER, the AA itself is not invariant.  Suppose after you converted to
an
AA with const strings as keys and values, you replaced one of the values
with a mutable string cast into a const string.

Yes, you're right.

invariant(char)[][] won't implicitly convert to const(char)[][]
either, for the same reason.
But...
invariant(char[])[] will implicitly conver to const(char[])[]

Yes, this makes sense, because you then wouldn't be able to change any
strings in the array, because the pointers in the strings are const.

But here's the odd thing...

invariant(char[])[] will implicitly conver to const(char[])[]
but
invariant(char[])[int] won't implicitly convert to const(char[])[int]

The only thing I can think of is that an AA does not do a copy-on-write when
adding a new element as normal arrays do, so you could potentially add a
member to the original AA which is not invariant.  Don't know if this is why
it's not allowed, or if it's even true :)

-Steve
```
Nov 15 2007
Reiner Pope <some address.com> writes:
```Janice Caron wrote:
On 11/15/07, Steven Schveighoffer <schveiguy yahoo.com> wrote:
Your first data type is an AA with invariant strings as keys and values.
HOWEVER, the AA itself is not invariant.  Suppose after you converted to an
AA with const strings as keys and values, you replaced one of the values
with a mutable string cast into a const string.

Yes, you're right.

invariant(char)[][] won't implicitly convert to const(char)[][]
either, for the same reason.
But...
invariant(char[])[] will implicitly conver to const(char[])[]

But here's the odd thing...

invariant(char[])[] will implicitly conver to const(char[])[]
but
invariant(char[])[int] won't implicitly convert to const(char[])[int]

The only difference is the int in the square brackets.

I think it's just the odd behaviour that invariant(char[])[] is actually
the same as invariant(char[][]), which is implicitly convertible to
const(char[][]), the same as const(char[])[].

-- Reiner
```
Nov 15 2007